vectorfind() upgrade: short needle, wildcard, hypermats, %nan 55/19055/19
Samuel GOUGEON [Wed, 8 Feb 2017 13:15:08 +0000 (14:15 +0100)]
 * SEP: http://mailinglists.scilab.org/Scilab-users-vectorfind-upgrade-SEP-tt4036885.html
 * New vectorfind page (PDF):
   http://mailinglists.scilab.org/attachment/4036887/0/vectorfind_PDF.zip

Change-Id: I4160490a89e13848e0ba4799bfa13faf50faf6ef

scilab/CHANGES.md
scilab/modules/elementary_functions/help/en_US/searchandsort/vectorfind.xml
scilab/modules/elementary_functions/help/ja_JP/searchandsort/vectorfind.xml [deleted file]
scilab/modules/elementary_functions/help/pt_BR/searchandsort/vectorfind.xml [deleted file]
scilab/modules/elementary_functions/help/ru_RU/searchandsort/vectorfind.xml
scilab/modules/elementary_functions/macros/vectorfind.sci
scilab/modules/elementary_functions/tests/nonreg_tests/bug_6862.dia.ref [deleted file]
scilab/modules/elementary_functions/tests/nonreg_tests/bug_6862.tst
scilab/modules/elementary_functions/tests/unit_tests/vectorfind.tst [new file with mode: 0644]
scilab/modules/helptools/data/pages/homepage-en_US.html

index 5d4f0a1..d23dc80 100644 (file)
@@ -158,14 +158,25 @@ Feature changes and additions
 * `twinkle` can now blink together several hierarchically independent objects, like a curve and its labels, etc.
 * `repmat` has been rewritten. It is 7 times faster now.
 * `plot` can now work in semi or bi-logarithmic mode with some input logflag.
-* `plotimplicit()` function added.
+* `plotimplicit` function added.
 * The default smarter grid_style value is now 7 instead of 3.
-* `weekday` accepts new date formats and syntaxes like `weekday()`, `weekday([2017 7 15])`, `weekday(2017, 7, 15)`, `weekday("15/7/2017")`,  `weekday("15-Jul-2017")`,  `weekday("2017-07-15")`, and `weekday("2017-07-15 21:53:17")`. A language option applying to the day names is now available.
+* `weekday` accepts new date formats and new syntaxes. A language option applying to the day names is now available.
+* `vectorfind` is upgraded:
+  - vectorfind(m, []) now returns [] instead of an error.
+  - A too long needle now returns [] instead of an error.
+  - %nan values never matched. They are now regularly processed, as other values.
+  - A needle shorter than the haystack size can now be used.
+  - A wildcard value matching any value of the haystack can now be specified and used in the needle. Actual matching ranges can then be returned: Options `joker` and `matching` added.
+  - Hypermatrices are now accepted as haystack.
+  - The probing direction can now be numeric: 1, 2, ..
+  - Returned indices can now be formatted with the new option `indType`.
+  - There were no unit tests. More than 100 tests are added.
+
 
 Help pages:
 -----------
 
-* overhauled / rewritten: `bitget`, `edit`, `factorial`
+* overhauled / rewritten: `bitget`, `edit`, `factorial`, `vectorfind`
 * fixed / improved:  `bench_run` `M_SWITCH`, `comet`, `comet3d`
 * Rewritten: `weekday`
 * Translations added:
index 2d9ffda..66fcb4e 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2008 - INRIA - Serge STEER
  * Copyright (C) 2008 - INRIA - Ramine NIKOUKHAH
  * Copyright (C) 2010 - DIGITEO - Vincent COUVERT
+ * Copyright (C) 2017 - Samuel GOUGEON
  *
  * Copyright (C) 2012 - 2016 - Scilab Enterprises
  *
  * along with this program.
  *
  -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="vectorfind" xml:lang="en">
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml"
+        xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook"
+        xmlns:scilab="http://www.scilab.org" xml:id="vectorfind" xml:lang="en">
     <refnamediv>
         <refname>vectorfind</refname>
-        <refpurpose>finds in a matrix rows or columns matching a vector</refpurpose>
+        <refpurpose>locates occurences of a (wildcarded) vector in a matrix or hypermatrix</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Syntax</title>
-        <synopsis>ind = vectorfind(m,v[,job])</synopsis>
+        <synopsis>
+            ind             = vectorfind(haystack, needle)
+            ind             = vectorfind(haystack, needle, dimAlong)
+            ind             = vectorfind(haystack, needle, dimAlong, ,indType)
+            [ind, matching] = vectorfind(haystack, needle, dimAlong, joker)
+            [ind, matching] = vectorfind(haystack, needle, dimAlong, joker, indType)
+        </synopsis>
     </refsynopsisdiv>
     <refsection>
         <title>Arguments</title>
         <variablelist>
             <varlistentry>
-                <term>m</term>
+                <term>haystack</term>
                 <listitem>
-                    <para>a matrix of any type (the same type as v).</para>
+                    <para>
+                    A matrix or hypermatrix of any type, possibly sparse encoded: The array in
+                    which the vector will be searched.
+                    </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>v</term>
+                <term>needle</term>
                 <listitem>
-                    <para>a vector of any type (the same type as m).</para>
+                    <para>
+                    The vector to be searched in the <varname>haystack</varname>, of the same type.
+                    If the <varname>haystack</varname> is sparse-encoded, the <varname>needle</varname>
+                    may be dense. In addition, if the <varname>haystack</varname> is boolean and a
+                    <varname>joker</varname> is used, the <varname>needle</varname> must be numerical
+                    instead of boolean. In this case, any of its non-zero components is
+                    <literal>%T</literal>
+                    </para>
+                    <note>
+                        <itemizedlist>
+                            <listitem>
+                                Decimal numbers, complex numbers, and encoded integers are considered
+                                of the same type: numerical.
+                            </listitem>
+                            <listitem>
+                                <literal>%nan</literal> values are accepted in the <varname>needle</varname>.
+                                They are processed in a regular way, as other values. They are matched only
+                                by <literal>%nan</literal> in the <varname>haystack</varname>.
+                            </listitem>
+                        </itemizedlist>
+                    </note>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>job</term>
+                <term>dimAlong</term>
                 <listitem>
-                    <para>A character string: optional flag with possible values "r" to look for matching rows
-                        or "c" to look for matching columns. Default value is "r".
+                    <para>Direction inside the <varname>haystack</varname> array along which the
+                    <varname>needle</varname> vector is searched. Possible values are
+                    <literal>"r"</literal> or <literal>1</literal> (along rows),
+                    <literal>"c"</literal> or <literal>2</literal> (along columns),
+                    or for an hypermatrix, any integer such that
+                    <literal>2 &lt; dimAlong &lt;= ndims(haystack)</literal>
+                    representing the index of the scanned dimension.
+                    By default, <literal>"r"</literal> is used.
+                    </para>
+                    <important>
+                        <varname>dimAlong</varname> is mandatory when a <varname>joker</varname>
+                        or <varname>indType</varname> is specified.
+                    </important>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>joker</term>
+                <listitem>
+                    <para>
+                    Single element of <varname>needle</varname>'s data type.
+                    The <varname>needle</varname> components equal to the <varname>joker</varname>
+                    are ignored (they match/accept any values from the <varname>haystack</varname>).
+                    </para>
+                    <para>
+                        When the haystack is boolean, the <varname>joker</varname> must be a
+                        non-zero number.
+                    </para>
+                    <para>
+                        To skip the <varname>joker</varname>, specify
+                        <literal>..dimAlong, ,indType</literal> with no joker value.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>indType</term>
+                <listitem>
+                    <para>Single case-insensitive word among <literal>""</literal>
+                    (empty text = default), <literal>"headIJK"</literal>, and <literal>"headN"</literal>:
+                    Specifies the format or returned indices. See here-below the description of
+                    <varname>ind</varname>.
                     </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                 <term>ind</term>
                 <listitem>
-                    <para>row vector containing indices of matching rows or columns</para>
+                    <para>
+                    <itemizedlist>
+                        <listitem>
+                            <para>
+                            When the <varname>needle</varname> is longer than the
+                            <varname>haystack</varname> size along the chosen dimension
+                            <varname>dimAlong</varname>, <varname>ind=[]</varname> is returned.
+                            </para>
+                        </listitem>
+                        <listitem>
+                            <para>
+                            When the <varname>needle</varname>'s length matches the
+                            <varname>haystack</varname> size along the chosen dimension,
+                            <itemizedlist>
+                                <listitem>
+                                    <para>
+                                    <emphasis role="bold">By default</emphasis>
+                                    (<varname>indType==""</varname>):
+                                    <varname>ind</varname> is a row vector containing the indices
+                                    of matching rows or columns of the haystack. In case of hypermatrix,
+                                    returned indices of matching ranges are linearized accross all
+                                    dimensions but the <varname>dimAlong</varname> one (see examples).
+                                    </para>
+                                </listitem>
+                                <listitem>
+                                    <para>
+                                    <emphasis role="bold">indType="headN"</emphasis>:
+                                    <varname>ind</varname> is the row vector of
+                                    <emphasis role="italic">linear</emphasis> indices in
+                                    the <varname>haystack</varname> of the heading component of its
+                                    matching rows, columns, or higher ranges.
+                                    </para>
+                                </listitem>
+                                <listitem>
+                                    <para>
+                                    <emphasis role="bold">indType="headIJK"</emphasis>:
+                                    <varname>ind</varname> is a matrix: Each row returns the
+                                    <literal>[i j ..]</literal>
+                                    indices in the <varname>haystack</varname> of the heading
+                                    component of its matching ranges (rows, columns, or higher ranges).
+                                    <varname>ind</varname> has as many rows as there are matching
+                                    ranges in the <varname>haystack</varname>.
+                                    </para>
+                                </listitem>
+                            </itemizedlist>
+                            </para>
+                        </listitem>
+                        <listitem>
+                            <para>
+                            Otherwise (short needle): By default,
+                            <varname>ind</varname> is the row vector of linear indices of the
+                            components of the <varname>haystack</varname> where matching ranges
+                            start. Using the <literal>indType="headN"</literal> option does
+                            nothing more. Using <literal>indType="headIJK"</literal> returns
+                            <varname>ind</varname> as a matrix of <literal>[i j k ..]</literal>
+                            indices, as described here-above.
+                            </para>
+                        </listitem>
+                    </itemizedlist>
+                    </para>
+                    <note>Returned indices are sorted in increasing order.</note>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>matching</term>
+                <listitem>
+                    <para>When a joker is used, this <varname>matching</varname> optional output
+                    is a matrix of haystack's data type returning the actual matching ranges:
+                    The matching range number #i is returned in the row <literal>matching(i,:)</literal>.
+                    </para>
+                    <note>
+                        When the <varname>haystack</varname> is sparse-encoded,
+                        the <varname>matching</varname> matrix is sparse as well.
+                    </note>
                 </listitem>
             </varlistentry>
         </variablelist>
     </refsection>
     <refsection>
         <title>Description</title>
-        <para>Finds in a matrix rows or columns matching a vector.</para>
+        <para>
+            <literal>vectorfind()</literal> looks for a given series of values (needle) in a
+            haystack array, along a given right direction/dimension: width (rows), height (columns),
+            thickness (like RGB pixels), etc. The needle may be as long or shorter than the size
+            of the probed side of the haystack.
+        </para>
+        <para>
+            A special value so-called <emphasis role="italic">joker</emphasis> may be specified.
+            Then this value works as a wildcard where it occurs in the needle vector.
+            Since this value is no longer selective -- ANY value from the haystack matches at its
+            position --, it can't simultaneously be used in the needle as a selective one.
+            In practical, any value not present in the haystack makes necessarily a good joker.
+            However, this condition is not mandatory.
+        </para>
+        <para>
+            Consequence: When the haystack is boolean, the joker -- and so the needle vector as
+            well -- must be numerical. Indeed, it would be otherwise impossible to choose
+            a joker value out of the {%T, %F} limited set of values.
+        </para>
+        <para>
+            When such a wildcard is used, actual values in matching ranges are not fixed. It is
+            then possible to retrieve them thanks to the
+            <literal>matching</literal> optional output. Otherwise, <literal>matching</literal>
+            is empty (it is a trivial repetition of the needle vector).
+        </para>
+        <refsect3>
+            <title>Search in hypermatrices</title>
+            <para>
+            Using <literal>vectorfind()</literal> with an hypermatrix haystack deserves some
+            special attention:
+            <itemizedlist>
+                <listitem>
+                    <para>About the direction value <literal>dimAlong</literal>:
+                    </para>
+                    <para>
+                        For instance, we
+                       can then probe the haystack array in "thickness", i.e.
+                       <emphasis role="italic">accross</emphasis> its successive layers
+                       <literal>haystack(:,:,#,..)</literal>. To do so, we will here specify
+                       <literal>dimAlong = 3</literal>.
+                    </para>
+                    <para>
+                    Like for matrices, this kind of high-dimension array can be
+                    scanned <emphasis role="italic">along</emphasis> its rows or columns.
+                    The corresponding <literal>dimAlong</literal> values have there some exceptions:
+                    <itemizedlist>
+                        <listitem>
+                            Searching the needle <emphasis role="italic">as rows</emphasis>
+                            is scanning the array
+                            <emphasis role="italic">accross its columns</emphasis>. Therefore,
+                            the <literal>dimAlong = "r"</literal> value should be equivalent to
+                            <literal>dimAlong = 2</literal> instead of 1!
+                        </listitem>
+                        <listitem>
+                            In the same way, searching the needle
+                            <emphasis role="italic">as columns</emphasis> is scanning the array
+                            <emphasis role="italic">accross its rows</emphasis>: The usual
+                            value
+                            <literal>dimAlong = "c"</literal> should be equivalent to
+                            <literal>dimAlong = 1</literal> instead of 2!
+                        </listitem>
+                    </itemizedlist>
+                    </para>
+                    <para>
+                    In order to not quit the common convention <literal>"r"&lt;=>1</literal>
+                    and <literal>"c"&lt;=>2</literal> used everywhere in Scilab,
+                    <literal>vectorfind()</literal> keeps and copes with it. But one should keep in
+                    mind the underlying switch, to have a clear understanding of the returned
+                    default indices when <literal>"r",1</literal> or <literal>"c",2</literal>
+                    are used.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                    About returned indices of matching rows, columns, "pixels"... when the needle
+                    is as long as the haystack side size and no <literal>indType</literal> option
+                    is used:
+                    </para>
+                    <para>
+                    Indices of matching ranges are then <emphasis role="italic">linear</emphasis>
+                    indices of components of the following subspaces:
+                    <itemizedlist>
+                        <listitem>
+                            With <literal>dimAlong = "r" = 1</literal>:
+                            in <literal>haystack(:,1,:,:..)</literal>
+                        </listitem>
+                        <listitem>
+                            With <literal>dimAlong = "c" = 2</literal>:
+                            in <literal>haystack(1,:,:,:..)</literal>
+                        </listitem>
+                        <listitem>
+                            With <literal>dimAlong = 3</literal>:
+                            in <literal>haystack(:,:,1,:..)</literal>
+                        </listitem>
+                        <listitem>
+                            With <literal>dimAlong = 4</literal>:
+                            in <literal>haystack(:,:,:,1,:..)</literal>.
+                        </listitem>
+                        <listitem>
+                            etc...
+                        </listitem>
+                    </itemizedlist>
+                    The case of a 3D and of a 4D array is dealt with in the Examples section.
+                    </para>
+                    Despite they are easy to understand and use for a simple matrix,
+                    it is somewhat hard to work with these linear indices in the haystack subspace
+                    to actually address the matching ranges in a ND-dimensional array with N>2.
+                    The option <literal>indType = "headN" | "headIJK</literal> will then return
+                    more workable indices refering to the whole <literal>haystack</literal> array.
+                </listitem>
+            </itemizedlist>
+            </para>
+        </refsect3>
     </refsection>
     <refsection>
         <title>Examples</title>
+        <para>
+            <emphasis role="bold">In a matrix of numbers:</emphasis>
+        </para>
         <programlisting role="example"><![CDATA[
-alr=[1,2,2;
-     1,2,1;
-     1,1,2;
-     1,1,1;
-     1,2,1];
+m = [ 1  0   1   2  2  1
+      2  2   0   1  0  2
+      0  2  %nan 2  1  2
+      2 %nan 1   0  1  2
+    ];
+vectorfind(m,[2 0 1 1], "c")            // => 5
+vectorfind(m,[2 0 1 1], "c",,"headN")   // => 17
+vectorfind(m,[2 0 1 1], "c",,"headIJK") // [1 5]
+
+// With a short needle:
+vectorfind(m,[2 2])                     // => [2 13]
+vectorfind(m,[2 2], "r",,"headN")       // same output
+vectorfind(m,[2 2], "r",,"headIJK")     // => [2 1 ; 1 4]
+vectorfind(m,[2 %nan])                  // => [4 7]
+
+// With a wildcard in the needle:
 
-ind = vectorfind(alr,[1,2,1],'r')
-ind = vectorfind(string(alr),string([1,2,1]),'r')
+// ex #1: All columns starting with 1 and ending with 2:
+[n, ma] = vectorfind(m,[1 .3 .3 2], "c", .3) // => n = [1 6], ma = [1 2 0 2; 1 2 2 2]
+
+// ex #2: All rows having a [2 * 2] range (wildcarded short needle):
+[n, ma] = vectorfind(m,[2 .3  2], "r", .3)   // => n = [7 15], ma = [2 %nan 2; 2 1 2]
+vectorfind(m,[2 .3  2], "r", .3, "headIJK")  // => [3 2 ; 3 4]
+                                             // Note: The %nan is matched by *
+ ]]></programlisting>
+        <para>
+            <emphasis role="bold">In a boolean matrix:</emphasis>
+        </para>
+        <programlisting role="example"><![CDATA[
+m = [0  0  0  1  1  0
+     0  1  1  1  0  1
+     1  1  0  1  1  1
+     1  0  1  0  0  1]==1
+// m  =
+//  F F F T T F
+//  F T T T F T
+//  T T F T T T
+//  T F T F F T
+vectorfind(m, [%F %T %T %F], "c")   // => 2
+vectorfind(m, [%T %T], "c")         // => [3 6 13 14 22 23]
+vectorfind(m, [1 1], "c")           // => error: same type expected
+// Joker => the needle is numerical:
+[n, ma] = vectorfind(m, [0 %nan 0 %nan 1], "r", %nan) // => n=[1 8], ma=[F F F T T ; F T F F T]
  ]]></programlisting>
+
+        <para>
+            <emphasis role="bold">In a tiny 8-color RGB image (3D hypermatrix of uint8 integers):</emphasis>
+        </para>
+        <programlisting role="example"><![CDATA[
+// Generating the array of color brightnesses:
+m = [1  1  1  1  1  0  1  0  0  0  1  0  1  0  0
+     1  1  0  0  0  0  1  0  1  0  1  1  1  1  1
+     1  1  0  1  0  1  1  0  0  1  1  0  0  1  0];
+m = uint8(matrix(m,3,5,3)*255)
+// m  =
+//(:,:,1)                   // RED layer
+//  255  255  255  255  255
+//  255  255    0    0    0
+//  255  255    0  255    0
+//(:,:,2)                   // GREEN layer
+//    0  255    0    0    0
+//    0  255    0  255    0
+//  255  255    0    0  255
+//(:,:,3)                   // BLUE layer
+//  255    0  255    0    0
+//  255  255  255  255  255
+//  255    0    0  255    0
+
+// Locates red pixels:
+vectorfind(m, [255 0 0], 3)             // => [10 13]
+vectorfind(m, [255 0 0], 3,,"headIJK")  // => [1 4 1 ; 1 5 1]
+
+// Pixels with Green & Blue ON, whatever is their Red channel:
+//   We may use a decimal-encoded needle (not a uint8).
+//   Then, %nan is a possible joker, that can't be in the uint8 image:
+vectorfind(m, [%nan 255 255], 3, %nan,"headIJK") // => [3 1 1; 2 2 1; 2 4 1]
+
+// Columns of 255:
+vectorfind(m, [255 255 255], "c")      // => [1 2 7 11]
+ ]]></programlisting>
+        <para>
+            <emphasis role="bold">In a 4D hypermatrix of text:</emphasis>
+        </para>
+        <programlisting role="example"><![CDATA[
+m  = [
+  "U"  "C"  "G"  "A"  "A"  "A"  "U"  "U"  "A"  "G"  "A"  "G"
+  "A"  "A"  "A"  "A"  "C"  "C"  "U"  "U"  "C"  "G"  "G"  "G"
+  "A"  "G"  "A"  "C"  "G"  "C"  "C"  "C"  "G"  "C"  "A"  "G"
+  "C"  "U"  "G"  "G"  "G"  "A"  "A"  "G"  "C"  "C"  "C"  "C"
+  "C"  "G"  "G"  "A"  "A"  "G"  "U"  "C"  "A"  "U"  "G"  "C"
+  ];
+m = matrix(m, 3, 5, 2, 2);
+// (:,:,1,1)
+// !U  C  A  G  A  !
+// !A  C  G  G  G  !
+// !A  C  U  A  G  !
+//(:,:,2,1)
+// !A  G  C  A  C  !
+// !A  A  G  A  A  !
+// !C  A  G  C  G  !
+//(:,:,1,2)
+// !U  A  U  C  G  !
+// !U  U  C  A  C  !
+// !C  U  G  C  A  !
+//(:,:,2,2)
+// !G  C  G  G  G  !
+// !G  U  A  G  C  !
+// !C  A  C  G  C  !
+
+vectorfind(m, ["A" "A" "C"], "c")       // => [6 9]
+vectorfind(m, [""  "G" "G"], "c", "")   // => [5 8 19]
+
+// Joker
+[n, ma] = vectorfind(m, ["" "G" "G"], "c", "", "headN") // => n=[13 22 55], ma=[A G G; C G G; G G G]
+vectorfind(m, ["" "C" "C"], "c", "", "headIJK") // => [1 2 1 1 ; 1 5 2 2]
+
+// Short needle
+vectorfind(m, ["C" "C"], "c",,"headIJK")        // => [1 2 1 1; 2 2 1 1; 2 5 2 2]
+
+// Short needle with joker
+vectorfind(m, ["A" "" "A"],"r","","headIJK")    // => [1 3 1 1 ; 2 2 2 1]
+]]></programlisting>
     </refsection>
     <refsection role="see also">
         <title>See also</title>
@@ -79,8 +451,55 @@ ind = vectorfind(string(alr),string([1,2,1]),'r')
                 <link linkend="find">find</link>
             </member>
             <member>
-                <link linkend="gsort">gsort</link>
+                <link linkend="members">members</link>
+            </member>
+            <member>
+                <link linkend="grep">grep</link>
             </member>
         </simplelist>
     </refsection>
+    <refsection role="history">
+        <title>History</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.1</revnumber>
+                <revdescription>
+                    <itemizedlist>
+                        <listitem>
+                            <literal>vectorfind(H,[])</literal> nows returns <literal>[]</literal>
+                            instead of an error.
+                        </listitem>
+                        <listitem>
+                            When the needle is too long, <literal>[]</literal> is now returned
+                            instead of an error.
+                        </listitem>
+                        <listitem>
+                            A needle shorter than the haystack size can now be used.
+                        </listitem>
+                        <listitem>
+                            A wildcard value matched by any value of the haystack can now be specified
+                            and used in the needle. Then, actual matching ranges can be returned:
+                            Options <literal>joker</literal> and <literal>matching</literal> added.
+                        </listitem>
+                        <listitem>
+                            Any <literal>%nan</literal> value occuring in the needle is now processed
+                            as any other regular value: It is matched by <literal>%nan</literal> in
+                            the haystack. It could formerly never be matched.
+                        </listitem>
+                        <listitem>
+                            Hypermatrices can now be processed as haystack.
+                        </listitem>
+                        <listitem>
+                            The probing direction <literal>dimAlong</literal> can now be numerical:
+                            1, 2, ..
+                        </listitem>
+                        <listitem>
+                            Option <literal>indType</literal> added.
+                        </listitem>
+                    </itemizedlist>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </refsection>
+
 </refentry>
diff --git a/scilab/modules/elementary_functions/help/ja_JP/searchandsort/vectorfind.xml b/scilab/modules/elementary_functions/help/ja_JP/searchandsort/vectorfind.xml
deleted file mode 100644 (file)
index 1cb3529..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!--
- * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- * Copyright (C) 2008 - INRIA - Serge STEER
- * Copyright (C) 2008 - INRIA - Ramine NIKOUKHAH
- *
- * Copyright (C) 2012 - 2016 - Scilab Enterprises
- *
- * This file is hereby licensed under the terms of the GNU GPL v2.0,
- * pursuant to article 5.3.4 of the CeCILL v.2.1.
- * This file was originally licensed under the terms of the CeCILL v2.1,
- * and continues to be available under such terms.
- * For more information, see the COPYING file which you should have received
- * along with this program.
- *
- -->
-
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="vectorfind" xml:lang="ja">
-
-    <refnamediv>
-
-        <refname>vectorfind</refname>
-
-        <refpurpose>ベクトルに一致する行列の行または列を見つける</refpurpose>
-
-    </refnamediv>
-
-    <refsynopsisdiv>
-
-        <title>呼び出し手順</title>
-
-        <synopsis>ind = vectorfind(m,v[,job])</synopsis>
-
-    </refsynopsisdiv>
-
-    <refsection>
-
-        <title>引数</title>
-
-        <variablelist>
-
-            <varlistentry>
-
-                <term>m</term>
-
-                <listitem>
-
-                    <para>任意の型の行列(vと同じ型)</para>
-
-                </listitem>
-
-            </varlistentry>
-
-            <varlistentry>
-
-                <term>v</term>
-
-                <listitem>
-
-                    <para>任意の型のベクトル(mと同じ型)</para>
-
-                </listitem>
-
-            </varlistentry>
-
-            <varlistentry>
-
-                <term>job</term>
-
-                <listitem>
-
-                    <para>
-
-                        1文字の文字列:
-
-                        オプションのフラグで,使用可能な値は,
-
-                        一致する行をさがす "r"
-
-                        または一致する列を探す "c"です.
-
-                        デフォルト値は "r"です.
-
-                    </para>
-
-                </listitem>
-
-            </varlistentry>
-
-            <varlistentry>
-
-                <term>ind</term>
-
-                <listitem>
-
-                    <para>一致した行または列の添字を含む行ベクトル</para>
-
-                </listitem>
-
-            </varlistentry>
-
-        </variablelist>
-
-    </refsection>
-
-    <refsection>
-
-        <title>説明</title>
-
-        <para>ベクトルに一致する行列の行または列を見つけます.</para>
-
-    </refsection>
-
-    <refsection>
-
-        <title>例</title>
-
-        <programlisting role="example"><![CDATA[
-alr=[1,2,2;
-     1,2,1;
-     1,1,2;
-     1,1,1;
-     1,2,1];
-ind = vectorfind(alr,[1,2,1],'r')
-ind = vectorfind(string(alr),string([1,2,1]),'r')
- ]]></programlisting>
-
-    </refsection>
-
-    <refsection role="see also">
-
-        <title>参照</title>
-
-        <simplelist type="inline">
-
-            <member>
-
-                <link linkend="find">find</link>
-
-            </member>
-
-            <member>
-
-                <link linkend="gsort">gsort</link>
-
-            </member>
-
-        </simplelist>
-
-    </refsection>
-
-</refentry>
-
diff --git a/scilab/modules/elementary_functions/help/pt_BR/searchandsort/vectorfind.xml b/scilab/modules/elementary_functions/help/pt_BR/searchandsort/vectorfind.xml
deleted file mode 100644 (file)
index 0f7e874..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- * Copyright (C) 2008 - INRIA - Serge STEER
- * Copyright (C) 2008 - INRIA - Ramine NIKOUKHAH
- *
- * Copyright (C) 2012 - 2016 - Scilab Enterprises
- *
- * This file is hereby licensed under the terms of the GNU GPL v2.0,
- * pursuant to article 5.3.4 of the CeCILL v.2.1.
- * This file was originally licensed under the terms of the CeCILL v2.1,
- * and continues to be available under such terms.
- * For more information, see the COPYING file which you should have received
- * along with this program.
- *
- -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="vectorfind" xml:lang="pt">
-    <refnamediv>
-        <refname>vectorfind</refname>
-        <refpurpose>acha, em uma matriz, linhas ou colunas que coincidem com um
-            vetor
-        </refpurpose>
-    </refnamediv>
-    <refsynopsisdiv>
-        <title>Seqüência de Chamamento</title>
-        <synopsis>ind = vectorfind(m,v,job)</synopsis>
-    </refsynopsisdiv>
-    <refsection>
-        <title>Parâmetros</title>
-        <variablelist>
-            <varlistentry>
-                <term>m</term>
-                <listitem>
-                    <para>uma matriz de qualquer tipo </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>v</term>
-                <listitem>
-                    <para>um vetor de qualquer tipo </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>job</term>
-                <listitem>
-                    <para>um string indicador com valores possíveis "r" para procura de
-                        linhas coincidentes ou "c" para procura de colunas coincidentes
-                    </para>
-                </listitem>
-            </varlistentry>
-            <varlistentry>
-                <term>ind</term>
-                <listitem>
-                    <para>vetor-linha contendo os índices das linhas ou colunas
-                        coincidentes
-                    </para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </refsection>
-    <refsection>
-        <title>Descrição</title>
-        <para>Acha, em uma matriz, as linhas ou colunas que coincidem com um dado
-            vetor.
-        </para>
-    </refsection>
-    <refsection>
-        <title>Exemplos</title>
-        <programlisting role="example"><![CDATA[
-alr=[1,2,2;
-     1,2,1;
-     1,1,2;
-     1,1,1;
-     1,2,1];
-ind = vectorfind(alr,[1,2,1],'r')
-ind = vectorfind(string(alr),string([1,2,1]),'r')
- ]]></programlisting>
-    </refsection>
-    <refsection role="see also">
-        <title>Ver Também</title>
-        <simplelist type="inline">
-            <member>
-                <link linkend="find">find</link>
-            </member>
-            <member>
-                <link linkend="gsort">gsort</link>
-            </member>
-        </simplelist>
-    </refsection>
-    <refsection>
-        <title>Autores</title>
-        <para>R. Nikoukhah, S. Steer INRIA</para>
-    </refsection>
-</refentry>
index cf97a3f..8a33c5f 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2008 - INRIA - Serge STEER
  * Copyright (C) 2008 - INRIA - Ramine NIKOUKHAH
  * Copyright (C) 2010 - DIGITEO - Vincent COUVERT
+ * Copyright (C) 2017 - Samuel GOUGEON
  *
  * Copyright (C) 2012 - 2016 - Scilab Enterprises
  *
  * along with this program.
  *
  -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:id="vectorfind" xml:lang="ru">
+<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:svg="http://www.w3.org/2000/svg" xmlns:ns5="http://www.w3.org/1999/xhtml"
+        xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook"
+        xmlns:scilab="http://www.scilab.org" xml:id="vectorfind" xml:lang="ru">
     <refnamediv>
         <refname>vectorfind</refname>
-        <refpurpose>ищет в строках или столбцах матриц совпадения с вектором</refpurpose>
+        <refpurpose>ищет расположение вектора (отмеченный символом групповой подстановки) в матрице или гиперматрице</refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Синтаксис</title>
-        <synopsis>ind = vectorfind(m,v[,job])</synopsis>
+        <synopsis>
+            ind             = vectorfind(haystack, needle)
+            ind             = vectorfind(haystack, needle, dimAlong)
+            ind             = vectorfind(haystack, needle, dimAlong, ,indType)
+            [ind, matching] = vectorfind(haystack, needle, dimAlong, joker)
+            [ind, matching] = vectorfind(haystack, needle, dimAlong, joker, indType)
+        </synopsis>
     </refsynopsisdiv>
     <refsection>
         <title>Аргументы</title>
         <variablelist>
             <varlistentry>
-                <term>m</term>
+                <term>haystack</term>
                 <listitem>
-                    <para>матрица любого типа (того же типа, что и v).</para>
+                    <para>
+                    Матрица или гиперматрица любого типа, возможно разрежённая: массив в
+            котором будет идти поиск вектора.
+                    </para>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>needle</term>
+                <listitem>
+                    <para>
+                    Вектор, который надо искать в <varname>haystack</varname>, того же самого типа.
+            Если <varname>haystack</varname> является разрежённой, то <varname>needle</varname>
+            может быть неразрежённой. К тому же, если <varname>haystack</varname> является
+            логической и используется <varname>joker</varname>, то <varname>needle</varname>
+            должна быть числовой, а не логической. В этом случае любой её ненулевой элемент
+            считается равным <literal>%T</literal>.
+                    </para>
+                    <note>
+                        <itemizedlist>
+                            <listitem>
+                                Десятичные числа, комплексные числа и кодированные целые числа считаются
+                одним типом: числовым.
+                            </listitem>
+                            <listitem>
+                                Значения <literal>%nan</literal> принимаются в <varname>needle</varname>.
+                Они обрабатываются обычным способом, как и другие значения. Они совпадают
+                только с <literal>%nan</literal> в <varname>haystack</varname>.
+                            </listitem>
+                        </itemizedlist>
+                    </note>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>dimAlong</term>
+                <listitem>
+                    <para>
+              Направление внутри массива <varname>haystack</varname> вдоль которого идёт поиск
+              вектора <varname>needle</varname>. Возможными значениями являются <literal>"r"</literal>
+              или <literal>1</literal> (вдоль строк), <literal>"c"</literal> или <literal>2</literal>
+              (вдоль столбцов) или для гиперматрицы любое целое значение, такое, что
+              <literal>2 &lt; dimAlong &lt;= ndims(haystack)</literal>, представляющее индекс сканируемого измерения. По умолчанию используется <literal>"r"</literal>.
+                    </para>
+                    <important>
+                        <varname>dimAlong</varname> обязателен, когда определён <varname>joker</varname>
+                        или <varname>indType</varname>.
+                    </important>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>v</term>
+                <term>joker</term>
                 <listitem>
-                    <para>вектор любого типа (того же типа, что и m).</para>
+                    <para>
+              Одиночный элемент типа данных <varname>needle</varname>. Элементы <varname>needle</varname>,
+              равные значению <varname>joker</varname> игнорируются (сопоставляются/принимаются любые
+              значения из <varname>haystack</varname>).
+                    </para>
+                    <para>
+              Когда <varname>haystack</varname> является логическим, то <varname>joker</varname>
+              должно быть ненулевым числом.
+                    </para>
+                    <para>
+              Чтобы пропустить <varname>joker</varname>, укажите
+              <literal>..dimAlong, ,indType</literal> без значения <varname>joker</varname>.
+                    </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
-                <term>job</term>
+                <term>indType</term>
                 <listitem>
                     <para>
-                        Символьная строка: необязательный флаг с возможными значениями "r" для поиска совпадений строк или "c" для поиска совпадений столбцов. По умолчанию значение  "r".
+              Одиночное нечувствительное к регистру слово внутри кавычек <literal>""</literal>
+              (по умолчанию без текста), <literal>"headIJK"</literal> и <literal>"headN"</literal>:
+              Определяет формат или индексы. Смотрите ниже описание переменной <varname>ind</varname>.
                     </para>
                 </listitem>
             </varlistentry>
             <varlistentry>
                 <term>ind</term>
                 <listitem>
-                    <para>вектор-строка, содержащая индексы совпадений строк или столбцов</para>
+                    <para>
+                    <itemizedlist>
+                        <listitem>
+                            <para>
+                  Если <varname>needle</varname> по размеру больше, чем <varname>haystack</varname>,
+                  в выбранной размерности <varname>dimAlong</varname>, и возвращается
+                  <varname>ind=[]</varname>.
+                            </para>
+                        </listitem>
+                        <listitem>
+                            <para>
+                  Если длина <varname>needle</varname> соответствует по размеру <varname>haystack</varname>
+                  по выбранной размерности:
+                            <itemizedlist>
+                                <listitem>
+                                    <para>
+                                    <emphasis role="bold">По умолчанию</emphasis>
+                                    (<varname>indType==""</varname>):
+                                    <varname>ind</varname> является вектором-строкой, содержащей индексы совпавших
+                    строк и столбцов <varname>haystack</varname>. В случае гиперматрицы возвращаемые
+                    индексы совпавших диапазонов линеаризованы через все размерности кроме одной
+                    <varname>dimAlong</varname> (см. примеры).
+                                    </para>
+                                </listitem>
+                                <listitem>
+                                    <para>
+                                    <emphasis role="bold">indType="headN"</emphasis>:
+                                    <varname>ind</varname> является  вектором-строкой <emphasis role="italic">линейных</emphasis>
+                    индексов в <varname>haystack</varname> первых элементов совпавших строк, столбцов и более высоких диапазонов.
+                                    </para>
+                                </listitem>
+                                <listitem>
+                                    <para>
+                                    <emphasis role="bold">indType="headIJK"</emphasis>:
+                                    <varname>ind</varname> является матрицей: каждая строка возвращает
+                                    индексы <literal>[i j ..]</literal> в <varname>haystack</varname> первых
+                    элементов совпавших диапазонов (строки, столбцы или более высокие диапазоны).
+                                    <varname>ind</varname> имеет столько строк, сколько совпавших диапазонов в
+                    <varname>haystack</varname>.
+                                    </para>
+                                </listitem>
+                            </itemizedlist>
+                            </para>
+                        </listitem>
+                        <listitem>
+                            <para>
+                            В противном случае (короткая <varname>needle</varname>): По умолчанию,
+                            <varname>ind</varname> является  вектором-строкой линейных индексов элементов
+                <varname>haystack</varname>, где начинаются совпавшие диапазоны. Используя опцию
+                <literal>indType="headN"</literal> ни к чему не приводит. Использование
+                <literal>indType="headIJK"</literal> возвращает <varname>ind</varname> в виде матрицы
+                индексов <literal>[i j k ..]</literal>, как было описано выше.
+                            </para>
+                        </listitem>
+                    </itemizedlist>
+                    </para>
+                    <note>Возвращаемые индексы сортированы в порядке возрастания.</note>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>matching</term>
+                <listitem>
+                    <para>
+              Когда используется <varname>matching</varname> выходная необязательная переменная
+              <varname>matching</varname> является матрицей с типом данных, как у
+              <varname>haystack</varname>, возвращающей фактические диапазоны совпадения: диапазон
+              совпадения №i возвращается в строке <literal>matching(i,:)</literal>.
+                    </para>
+                    <note>
+                        Когда <varname>haystack</varname> является разрежённой, то матрица
+            <varname>matching</varname> тоже является разрежённой.
+                    </note>
                 </listitem>
             </varlistentry>
         </variablelist>
     </refsection>
     <refsection>
         <title>Описание</title>
-        <para>Ищет строки или столбцы матрицы, совпадающие с вектором.</para>
+        <para>
+            <literal>vectorfind()</literal> ищет указанную последовательность значений
+        <varname>needle</varname> (иголка) в массиве <varname>haystack</varname> (стог сена) по указанному
+        прямому направлению/измерению: ширина (строки), высота (столбцы), толщина (подобно пикселям RGB) и т.д.
+        Иголка <varname>needle</varname> может быть длиннее или короче, чем размер исследуемой стороны стога
+        сена <varname>haystack</varname>.
+        </para>
+        <para>
+        Может быть определено специальное значение, так называемый <emphasis role="italic">джокер</emphasis>.
+        Тогда это значение работает, как символ универсальной подстановки там, где он встречается в векторе иглы
+        <varname>needle</varname>. Поскольку это значение более нельзя выбирать, то -- ЛЮБОЕ значение после
+        совпадений в стогу сена <varname>haystack</varname> на своей позиции --, оно не может одновременно
+        использоваться в игле <varname>needle</varname> в качестве выбираемого. На практике любое значение,
+        не представленное в стоге сена <varname>haystack</varname>, обязательно требует хорошего джокера. Однако,
+        это условие не является обязательным.
+        </para>
+        <para>
+            Следовательно: когда стог сена <varname>haystack</varname> является логическим, то джокер -- а также
+        вектор иглы <varname>needle</varname> -- должен быть числовым. Действительно, в противном случае было
+        бы невозможно выбрать значение джокера из ограниченного множества значений <literal>{%T, %F}</literal>.
+        </para>
+        <para>
+        Когда такой символ универсальной подстановки используется, то фактические значения в совпавших
+        диапазонах не фиксируются. Тогда можно получить их благодаря необязательной выходной переменной
+        <varname>matching</varname>. В противном случае <varname>matching</varname> будет пустой (это
+        тривиальный повтор вектора иглы <varname>needle</varname>).
+        </para>
+        <refsect3>
+            <title>Поиск в гиперматрицах</title>
+            <para>
+          Использование <literal>vectorfind()</literal> с гиперматрицей в качестве <varname>haystack</varname>
+          заслуживает несколько особого внимания:
+            <itemizedlist>
+                <listitem>
+                    <para>О значении направления <literal>dimAlong</literal>:
+                    </para>
+                    <para>
+                        Например, мы можем затем исследовать массив <varname>haystack</varname> по "толщине",
+            то есть  <emphasis role="italic">сквозь</emphasis> её следующие друг за другом слои
+            <literal>haystack(:,:,#,..)</literal>. Чтобы так сделать, мы определим здесь
+            <literal>dimAlong = 3</literal>.
+                    </para>
+                    <para>
+              Как и для матриц, этот вид многомерного массива может быть просканирован
+              <emphasis role="italic">вдоль</emphasis> его строк или столбцов. Подходящие значения
+              <literal>dimAlong</literal> имеют некоторые исключения:
+                    <itemizedlist>
+                        <listitem>
+                Поиск иглы <emphasis role="italic">как строки</emphasis> сканирует массив
+                <emphasis role="italic">сквозь его столбцы</emphasis>. Следовательно,
+                значение <literal>dimAlong = "r"</literal> должно быть эквивалентно значению
+                <literal>dimAlong = 2</literal> вместо 1!
+                        </listitem>
+                        <listitem>
+                            Аналогично поиск иглы <emphasis role="italic">как столбцы</emphasis> сканирует массив
+                <emphasis role="italic">сквозь его строки</emphasis>: Обычное значение
+                            <literal>dimAlong = "c"</literal> должно быть эквивалентно значению
+                            <literal>dimAlong = 1</literal> вместо 2!
+                        </listitem>
+                    </itemizedlist>
+                    </para>
+                    <para>
+              Для того, чтобы не нарушать общую договорённость, о том что  <literal>"r"&lt;=>1</literal> и
+              <literal>"c"&lt;=>2</literal> используется везде в Scilab, <literal>vectorfind()</literal>
+              придерживается и справляется с ним. Но нужно иметь в виду лежащий в основе переключатель, чтобы
+              иметь чёткое понимание возвращаемых по умолчанию индексов, когда используются <literal>"r",1</literal>
+              или <literal>"c",2</literal>.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+              О возвращаемых индексах совпадающих строк, столбцов, "пикселей"... когда игла <varname>needle</varname>
+              такой же длины, как размер стороны стога сена <varname>haystack</varname> и опция
+              <literal>indType</literal> не используется:
+                    </para>
+                    <para>
+              Индексы совпадающих диапазонов являются <emphasis role="italic">линейными</emphasis>
+              индексами компонентов следующих подпространств:
+                    <itemizedlist>
+                        <listitem>
+                            С <literal>dimAlong = "r" = 1</literal>:
+                            в <literal>haystack(:,1,:,:..)</literal>
+                        </listitem>
+                        <listitem>
+                            С <literal>dimAlong = "c" = 2</literal>:
+                            в <literal>haystack(1,:,:,:..)</literal>
+                        </listitem>
+                        <listitem>
+                            С <literal>dimAlong = 3</literal>:
+                            в <literal>haystack(:,:,1,:..)</literal>
+                        </listitem>
+                        <listitem>
+                            С <literal>dimAlong = 4</literal>:
+                            в <literal>haystack(:,:,:,1,:..)</literal>.
+                        </listitem>
+                        <listitem>
+                            и др...
+                        </listitem>
+                    </itemizedlist>
+                    Случай трёх- и четырёхмерных массивов рассмотрен в разделе примеров.
+                    </para>
+            Несмотря на то, что легко понять и использовать для простых матриц, несколько трудно
+            работать с этими линейными индексами в подпространстве <literal>haystack</literal>,
+            чтобы фактически обращаться к совпадающим диапазонам в ND-мерном массиве с N>2.
+                    Необязательный параметр <literal>indType = "headN" | "headIJK</literal> затем вернёт
+            более удобные в работе индексы, обращающиеся ко всему массиву <literal>haystack</literal>.
+                </listitem>
+            </itemizedlist>
+            </para>
+        </refsect3>
     </refsection>
     <refsection>
         <title>Примеры</title>
+        <para>
+            <emphasis role="bold">В матрице чисел:</emphasis>
+        </para>
+        <programlisting role="example"><![CDATA[
+m = [ 1  0   1   2  2  1
+      2  2   0   1  0  2
+      0  2  %nan 2  1  2
+      2 %nan 1   0  1  2
+    ];
+vectorfind(m,[2 0 1 1], "c")            // => 5
+vectorfind(m,[2 0 1 1], "c",,"headN")   // => 17
+vectorfind(m,[2 0 1 1], "c",,"headIJK") // [1 5]
+// С короткой иглой:
+vectorfind(m,[2 2])                     // => [2 13]
+vectorfind(m,[2 2], "r",,"headN")       // тот же выходной параметр
+vectorfind(m,[2 2], "r",,"headIJK")     // => [2 1 ; 1 4]
+vectorfind(m,[2 %nan])                  // => [4 7]
+// С символом универсальной подстановки в игле:
+// пример №1: все столбцы начинаются с 1 и заканчиваются 2:
+[n, ma] = vectorfind(m,[1 .3 .3 2], "c", .3) // => n = [1 6], ma = [1 2 0 2; 1 2 2 2]
+// пример №2: все строки, имеющие диапазон [2 * 2] (короткая игла с символом универсальной подстановки):
+[n, ma] = vectorfind(m,[2 .3  2], "r", .3)   // => n = [7 15], ma = [2 %nan 2; 2 1 2]
+vectorfind(m,[2 .3  2], "r", .3, "headIJK")  // => [3 2 ; 3 4]
+                                             // Примечание: значение %nan соответствует *
+ ]]></programlisting>
+        <para>
+            <emphasis role="bold">Логическая матрица:</emphasis>
+        </para>
         <programlisting role="example"><![CDATA[
-alr=[1,2,2;
-     1,2,1;
-     1,1,2;
-     1,1,1;
-     1,2,1];
-
-ind = vectorfind(alr,[1,2,1],'r')
-ind = vectorfind(string(alr),string([1,2,1]),'r')
+m = [0  0  0  1  1  0
+     0  1  1  1  0  1
+     1  1  0  1  1  1
+     1  0  1  0  0  1]==1
+// m  =
+//  F F F T T F
+//  F T T T F T
+//  T T F T T T
+//  T F T F F T
+vectorfind(m, [%F %T %T %F], "c")   // => 2
+vectorfind(m, [%T %T], "c")         // => [3 6 13 14 22 23]
+vectorfind(m, [1 1], "c")           // => ошибка: ожидался тот же тип
+// джокер => игла является числовой:
+[n, ma] = vectorfind(m, [0 %nan 0 %nan 1], "r", %nan) // => n=[1 8], ma=[F F F T T ; F T F F T]
  ]]></programlisting>
+        <para>
+            <emphasis role="bold">В маленьком 8-цветном RGB-изображении (трёхмерная гиперматрица
+          целых чисел типа uint8):</emphasis>
+        </para>
+        <programlisting role="example"><![CDATA[
+// Формирование массива яркости цвета:
+m = [1  1  1  1  1  0  1  0  0  0  1  0  1  0  0
+     1  1  0  0  0  0  1  0  1  0  1  1  1  1  1
+     1  1  0  1  0  1  1  0  0  1  1  0  0  1  0];
+m = uint8(matrix(m,3,5,3)*255)
+// m  =
+//(:,:,1)                   // Красный слой
+//  255  255  255  255  255
+//  255  255    0    0    0
+//  255  255    0  255    0
+//(:,:,2)                   // Зелёный слой
+//    0  255    0    0    0
+//    0  255    0  255    0
+//  255  255    0    0  255
+//(:,:,3)                   // Синий слой
+//  255    0  255    0    0
+//  255  255  255  255  255
+//  255    0    0  255    0
+// Определяет позицию красных пикселей:
+vectorfind(m, [255 0 0], 3)             // => [10 13]
+vectorfind(m, [255 0 0], 3,,"headIJK")  // => [1 4 1 ; 1 5 1]
+// Пиксели с включённым зелёным и синим цветом, каким бы ни был их красный канал:
+//   Мы можем использовать десятично-кодированную иглу (не uint8).
+//   Тогда, %nan можно использовать в качестве джокера, который не может быт в изображении с типом uint8:
+vectorfind(m, [%nan 255 255], 3, %nan,"headIJK") // => [3 1 1; 2 2 1; 2 4 1]
+// Столбцы из 255:
+vectorfind(m, [255 255 255], "c")      // => [1 2 7 11]
+ ]]></programlisting>
+        <para>
+            <emphasis role="bold">В четырёхмерной текстовой гиперматрице:</emphasis>
+        </para>
+        <programlisting role="example"><![CDATA[
+m  = [
+  "U"  "C"  "G"  "A"  "A"  "A"  "U"  "U"  "A"  "G"  "A"  "G"
+  "A"  "A"  "A"  "A"  "C"  "C"  "U"  "U"  "C"  "G"  "G"  "G"
+  "A"  "G"  "A"  "C"  "G"  "C"  "C"  "C"  "G"  "C"  "A"  "G"
+  "C"  "U"  "G"  "G"  "G"  "A"  "A"  "G"  "C"  "C"  "C"  "C"
+  "C"  "G"  "G"  "A"  "A"  "G"  "U"  "C"  "A"  "U"  "G"  "C"
+  ];
+m = matrix(m, 3, 5, 2, 2);
+// (:,:,1,1)
+// !U  C  A  G  A  !
+// !A  C  G  G  G  !
+// !A  C  U  A  G  !
+//(:,:,2,1)
+// !A  G  C  A  C  !
+// !A  A  G  A  A  !
+// !C  A  G  C  G  !
+//(:,:,1,2)
+// !U  A  U  C  G  !
+// !U  U  C  A  C  !
+// !C  U  G  C  A  !
+//(:,:,2,2)
+// !G  C  G  G  G  !
+// !G  U  A  G  C  !
+// !C  A  C  G  C  !
+vectorfind(m, ["A" "A" "C"], "c")       // => [6 9]
+vectorfind(m, [""  "G" "G"], "c", "")   // => [5 8 19]
+// Джокер
+[n, ma] = vectorfind(m, ["" "G" "G"], "c", "", "headN") // => n=[13 22 55], ma=[A G G; C G G; G G G]
+vectorfind(m, ["" "C" "C"], "c", "", "headIJK") // => [1 2 1 1 ; 1 5 2 2]
+// Короткая игла
+vectorfind(m, ["C" "C"], "c",,"headIJK")        // => [1 2 1 1; 2 2 1 1; 2 5 2 2]
+// Короткая игла с джокером
+vectorfind(m, ["A" "" "A"],"r","","headIJK")    // => [1 3 1 1 ; 2 2 2 1]
+]]></programlisting>
     </refsection>
     <refsection role="see also">
         <title>Смотрите также</title>
@@ -79,8 +433,53 @@ ind = vectorfind(string(alr),string([1,2,1]),'r')
                 <link linkend="find">find</link>
             </member>
             <member>
-                <link linkend="gsort">gsort</link>
+                <link linkend="members">members</link>
+            </member>
+            <member>
+                <link linkend="grep">grep</link>
             </member>
         </simplelist>
     </refsection>
+    <refsection role="history">
+        <title>История</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.1</revnumber>
+                <revdescription>
+                    <itemizedlist>
+                        <listitem>
+                            <literal>vectorfind(H,[])</literal> теперь возвращает <literal>[]</literal>
+                            вместо ошибки.
+                        </listitem>
+                        <listitem>
+                            Когда игла слишком длинная, теперь вместо ошибки возвращается <literal>[]</literal>.
+                        </listitem>
+                        <listitem>
+                            Теперь может быть использована игла, короче, чем размер стога сена.
+                        </listitem>
+                        <listitem>
+                Значение символа универсальной подстановки, совпавшее с любым значением стога сена теперь может быть
+                определён и использован в качестве иглы. Затем могут быть возвращены фактически совпадающие диапазоны:
+                добавлены необязательные параметры <literal>joker</literal> и <literal>matching</literal>.
+                        </listitem>
+                        <listitem>
+                            Любое значение <literal>%nan</literal>, встреченное в игле, теперь обрабатывается
+                как любое иное регулярное значение: оно соответствует значению <literal>%nan</literal>
+                в стоге сена. Оно ранее никогда не соответствовало.
+                        </listitem>
+                        <listitem>
+                            Гиперматрицы могут теперь обрабатываться в качестве стога сена.
+                        </listitem>
+                        <listitem>
+                            Исследуемое направление <literal>dimAlong</literal> теперь может быть числовым:
+                            1, 2, ..
+                        </listitem>
+                        <listitem>
+                            Добавлен необязательный параметр <literal>indType</literal>.
+                        </listitem>
+                    </itemizedlist>
+                </revdescription>
+            </revision>
+        </revhistory>
+    </refsection>
 </refentry>
index 91edf2a..2e782a4 100644 (file)
@@ -1,6 +1,7 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) INRIA
 // Copyright (C) 2010 - DIGITEO - Vincent COUVERT
+// Copyright (C) 2017 - Samuel GOUGEON
 //
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
 //
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
-function ind=vectorfind(m,v,job)
+function [ind, matching] = vectorfind(m, v, way, joker, indType)
+    // way: "r" or 1, "c" or 2, 2 < i < ndims(m)
+    // indType: "" (default), "headIJK", "headN"
 
-    rhs = argn(2);
+    rhs = argn(2)
 
     // Check number of inputs, at least 2 needed
-    if rhs < 2 then
-        error(msprintf(gettext("%s: Wrong number of input arguments: %d or %d expected.\n"), "vectorfind", 2, 3));
+    if rhs < 2 | rhs > 5 then
+        msg = _("%s: Wrong number of input arguments: %d to %d expected.\n")
+        error(msprintf(msg, "vectorfind", 2, 5))
     end
 
-    // Set default value for job if not given
-    if rhs == 2 then
-        job = "r";
+    if ~isdef("joker", "l") | type(joker) == 0 then
+        joker = []
     end
 
-    // Check that m and v have the same type
-    if typeof(m) <> typeof(v) then
-        error(msprintf(gettext("%s: Incompatible input arguments #%d and #%d: Same type expected.\n"), "vectorfind", 1, 2));
+    // Types of m and v must be compatible:
+    ok = (type(m) == type(v)) | ..
+    (or(type(m) == [1 5 8]) & or(type(v) == [1 5 8])) | ..
+    (type(m) == 4 & joker ~=[] & or(type(v) == [1 5 8]));
+
+    if ~ok then
+        msg = _("%s: Incompatible input arguments #%d and #%d: Same type expected.\n");
+        error(msprintf(msg, "vectorfind", 1, 2))
     end
 
-    if min(size(v))<>1 then
-        error(msprintf(gettext("%s: Wrong size for input argument #%d: Vector expected.\n"),"vectorfind",2));
+    // Checking the needle:
+    if v == [] then
+        ind = []
+        return
+    end
+    if ~isvector(v) & ~isscalar(v) then
+        msg = _("%s: Wrong size for input argument #%d: Vector expected.\n")
+        error(msprintf(msg, "vectorfind", 2))
+    else
+        v = v(:);
     end
 
-    if convstr(part(job,1))=="r" then
-        if size(v,"*")<>size(m,2) then
-            error(msprintf(gettext("%s: Wrong size for input arguments: Incompatible sizes.\n"),"vectorfind"));
+    Ndim = ndims(m);
+    // Checking the direction:
+    if ~isdef("way", "l") | type(way) == 0 then
+        way = 1         // Default direction
+    elseif size(way, "*") > 1 then
+        msg = _("%s: Argument #%d: Scalar (1 element) expected.\n");
+        error(msprintf(msg, "vectorfind", 3));
+    elseif and(type(way) ~= [1 10]) then
+        msg = _("%s: Argument #%d: Text or integer decimal expected.\n");
+        error(msprintf(msg, "vectorfind", 3));
+    elseif and(way ~= ["r" "c"]) & and(way ~= (1:Ndim)) then
+        msg = _("%s: Argument #%d: Must be in the set {%s}.\n");
+        tmp = msprintf("""r"",""c"",1,..,%d", Ndim);
+        error(msprintf(msg, "vectorfind",3, tmp))
+    else
+        if way == "r" then
+            way = 1
+        elseif way == "c" then
+            way = 2
         end
-        ind=1:size(m,1)
-        for k=1:size(m,2)
-            ind=ind(find(m(ind,k)==v(k)));
-            if ind==[] then
-                break
+    end
+
+    // Checking the joker
+    if joker ~= [] & size(joker,"*") ~= 1 then
+        msg = _("%s: Wrong size for input argument #%d: Scalar expected.\n")
+        error(msprintf(msg, "vectorfind",4))
+    end
+
+    if joker ~= [] & ((or(type(joker) == [1 5 8]) & ~or(type(v) == [1 5 8])) | ..
+        (or(type(joker) == [2 10]) & type(joker) ~= type(v)))
+        msg = _("%s: Incompatible input arguments #%d and #%d: Same type expected.\n")
+        error(msprintf(msg, "vectorfind", 2, 4))
+    end
+    if type(m) == 4 & joker ~= [] & joker == 0 then
+        msg = _("%s: Argument #%d: non-zero number expected.\n")
+        error(msprintf(msg, "vectorfind", 4))
+    end
+    // Checkinh indType
+    if ~isdef("indType", "l") | type(indType) == 0 then
+        indType = ""
+    elseif type(indType) ~= 10 then
+        msg = _("%s: Argument #%d: Text expected.\n");
+        error(msprintf(msg, "vectorfind", 5));
+    elseif size(indType, "*") > 1 then
+        msg = _("%s: Argument #%d: Scalar (1 element) expected.\n");
+        error(msprintf(msg, "vectorfind", 5));
+    else
+        indType = convstr(indType);
+        if ~or(indType == ["" "headijk" "headn"]) then
+            msg = _("%s: Argument #%d: Must be in the set {%s}.\n");
+            error(msprintf(msg, "vectorfind", 5,""""", ""headIJK"", ""headN"""));
+        end
+    end
+
+    sm = size(m)
+    sv = size(v,"*")
+    matching = [];
+
+    // Normalizing m and v shapes: setting the direction along COLUMNS
+    if Ndim == 2 then
+        if way == 1 then
+            m = m.';
+        end
+    else    // Ndim>2
+        i = 1:Ndim;
+        if way == 1 then
+            i([1 2]) = [2 1];
+            m = permute(m,i);
+            m = matrix(m, sm(2), -1);
+        elseif way == 2 then
+            m = matrix(m, sm(1), -1)
+        elseif way==Ndim
+            m = matrix(m, -1, sm(way)).';
+        else
+            m = matrix(m, prod(sm(1:way-1)), sm(way), -1);
+            m = permute(m, [2 1 3]);
+            m = matrix(m, sm(way), -1);
+        end
+    end
+    // flag for partial v
+    partial = sv < size(m, 1)
+
+    //
+    if sv > size(m,1)
+        ind = []
+        return
+
+    elseif partial // v shorter than m size
+        cs = size(m,1) - sv
+        k = ndgrid(1:sv, 1:(cs+1)) + ones(sv,1)*(0:cs)
+        M = matrix(m(k(:),:), sv, -1)
+        ind = vectorfind(M, v, "c", joker)
+        if joker~=[]
+            matching = M(:,ind).';
+        end
+        clear M
+        // We compute k = index of start of matching inside the full range
+        if ind ~= [] then
+            k = modulo(ind, cs + 1);
+            k(k == 0) = cs + 1;
+        else
+            k = []
+        end
+        ind = ceil(ind / (cs + 1));  // linearized indices of full vectors
+
+    else
+        // Performing the detection:
+        // ------------------------
+        // Selecting only needle's components not being the joker
+        if joker ~= [] then
+            if type(v) == 1 & isnan(joker) then
+                c = find(~isnan(v))
+            else
+                c = find(v ~= joker)
             end
+        else
+            c = 1:size(v, "*")
         end
-    elseif convstr(part(job,1))=="c" then
-        if size(v,"*")<>size(m,1) then
-            error(msprintf(gettext("%s: Wrong size for input arguments: Incompatible sizes.\n"),"vectorfind"));
+        if type(m) == 4 & or(type(v) == [1 5 8]) then
+            v = (v ~= 0);
         end
-        ind=1:size(m,2)
-        for k=1:size(m,1)
-            ind=ind(find(m(k,ind)==v(k)))
-            if ind==[] then
+
+        ind = 1:size(m, 2);
+        for k = c   // Loop over needle components not being jokers
+            if isnan(v(k)) then
+                i = find(isnan(m(k, ind)));
+            else
+                i = find(m(k, ind) == v(k));
+            end
+            ind = ind(i);
+            if ind == [] then
                 break
             end
         end
-    else
-        error(msprintf(gettext("%s: Wrong value for input argument #%d: ''%s'' or ''%s'' expected.\n"),"vectorfind",3,"r[ow]","c[olumn]"));
+        if joker ~= [] then
+            matching = m(:,ind).';
+        end
     end
-endfunction
 
+    // Post-processing output indices
+    // ------------------------------
+    if indType ~= "" | partial then
+        if way == 1 then
+            way = 2
+        elseif way == 2 then
+            way = 1
+        end
+        i = 1:Ndim;
+        i(way) = [];
+        I = ind2sub(sm(i), ind);
+        I2 = [];
+        if way>1
+            I2 = I(:, 1:way-1);
+        end
+        if ~partial then
+            I2 = [I2 ones(I(:,1))];
+        else
+            I2 = [I2 k(:)];
+        end
+        if way < Ndim then
+            I2 = [I2 I(:,way:$)];
+        end
+        if indType == "headijk" then
+            ind = I2;
+            if partial then
+                [tmp, k] = gsort(ind(:,$:-1:1), "lr", "i");
+                ind = ind(k,:);
+                // otherwise: it should already be sorted
+            end
+        elseif indType=="headn" | partial then
+            ind = gsort(sub2ind(sm,I2)', "g", "i");
+        end
+    end
+endfunction
diff --git a/scilab/modules/elementary_functions/tests/nonreg_tests/bug_6862.dia.ref b/scilab/modules/elementary_functions/tests/nonreg_tests/bug_6862.dia.ref
deleted file mode 100644 (file)
index 93a36aa..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// =============================================================================
-// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) 2010 - DIGITEO - Vincent COUVERT
-//
-//  This file is distributed under the same license as the Scilab package.
-// =============================================================================
-// <-- CLI SHELL MODE -->
-// <-- Non-regression test for bug 6862 -->
-//
-// <-- Bugzilla URL -->
-// http://bugzilla.scilab.org/show_bug.cgi?id=6862
-//
-// <-- Short Description -->
-// vectorfind(M,V,dir)
-// * The number of mandatory entries is not checked.
-// * typeof(M)==typeof(V) is not checked.
-// Check that at least 2 inputs are needed
-ierr = execstr("vectorfind([2 2])", "errcatch");
-errmsg = msprintf(gettext("%s: Wrong number of input arguments: %d or %d expected.\n"), "vectorfind", 2, 3);
-if ierr==0 | (lasterror() <> errmsg) then bugmes();quit;end
-// Check that "r" option is added by default
-if vectorfind([2 2], [2 2]) <> vectorfind([2 2], [2 2], "r") then bugmes();quit;end
-// Check that an error message is returned if first and second input arguments have not the same type
-ierr = execstr("vectorfind([1 2], string([1 2]))", "errcatch");
-errmsg = msprintf(gettext("%s: Incompatible input arguments #%d and #%d: Same type expected.\n"), "vectorfind", 1, 2);
-if ierr==0 | lasterror() <> errmsg then bugmes();quit;end
index 9112086..c6ccd60 100644 (file)
@@ -6,6 +6,7 @@
 // =============================================================================
 
 // <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
 
 // <-- Non-regression test for bug 6862 -->
 //
 // * typeof(M)==typeof(V) is not checked.
 
 // Check that at least 2 inputs are needed
-ierr = execstr("vectorfind([2 2])", "errcatch");
-errmsg = msprintf(gettext("%s: Wrong number of input arguments: %d or %d expected.\n"), "vectorfind", 2, 3);
-if ierr==0 | (lasterror() <> errmsg) then pause; end
+msg = msprintf(gettext("%s: Wrong number of input arguments: %d to %d expected.\n"), "vectorfind", 2, 5);
+assert_checkerror("vectorfind([2 2])", msg);
 
 // Check that "r" option is added by default
-if vectorfind([2 2], [2 2]) <> vectorfind([2 2], [2 2], "r") then pause; end
+assert_checkequal(vectorfind([2 2], [2 2]), vectorfind([2 2], [2 2], "r"));
 
 // Check that an error message is returned if first and second input arguments have not the same type
-ierr = execstr("vectorfind([1 2], string([1 2]))", "errcatch");
-errmsg = msprintf(gettext("%s: Incompatible input arguments #%d and #%d: Same type expected.\n"), "vectorfind", 1, 2);
-if ierr==0 | lasterror() <> errmsg then pause; end
+msg = msprintf(gettext("%s: Incompatible input arguments #%d and #%d: Same type expected.\n"), "vectorfind", 1, 2);
+assert_checkerror("vectorfind([1 2], string([1 2]))", msg);
diff --git a/scilab/modules/elementary_functions/tests/unit_tests/vectorfind.tst b/scilab/modules/elementary_functions/tests/unit_tests/vectorfind.tst
new file mode 100644 (file)
index 0000000..29997aa
--- /dev/null
@@ -0,0 +1,417 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2017 - Samuel GOUGEON
+//
+// This file is hereby licensed under the terms of the GNU GPL v2.0,
+// pursuant to article 5.3.4 of the CeCILL v.2.1.
+// This file was originally licensed under the terms of the CeCILL v2.1,
+// and continues to be available under such terms.
+// For more information, see the COPYING file which you should have received
+// along with this program.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+//
+// <-- Unit test of vectorfind() -->
+
+m = [
+  1  0  0  0  1  0  1  0  1  0  0  1  1  1  1
+  0  0  1  0  0  1  0  1  0  0  0  0  0  0  0
+  0  1  1  1  0  0  1  1  1  0  1  1  0  0  1
+  0  0  1  0  1  0  1  0  1  0  0  0  0  0  1
+  ];
+H = [1 0 0 1 2 0 0 0 1 0 2 1 2 2 1 0 1 2
+     2 2 1 0 0 2 1 0 2 0 1 2 1 0 0 1 0 0];
+H = matrix(H, [2 3 3 2])
+// --> H = matrix(H, [2 3 3 2])
+//  H  =
+// (:,:,1,1)
+//    1   0   0
+//    2   2   1
+// (:,:,2,1)
+//    1   2   0
+//    0   0   2
+// (:,:,3,1)
+//    0   0   1
+//    1   0   2
+//
+// (:,:,1,2)
+//    0   2   1
+//    0   1   2
+// (:,:,2,2)
+//    2   2   1
+//    1   0   0
+// (:,:,3,2)
+//    0   1   2
+//    1   0   0
+
+// ==================
+// CHECKING ARGUMENTS
+// ==================
+// Number of arguments
+assert_checkfalse(execstr("vectorfind()","errcatch")==0);
+assert_checkfalse(execstr("vectorfind(m,[1 0 1 0],""c"",2,"""",%t)","errcatch")==0);
+assert_checktrue (execstr("a=vectorfind(m,[1 0 1 0],""c"")","errcatch")==0);
+assert_checktrue (execstr("[a,b]=vectorfind(m,[1 0 1 0],""c"")","errcatch")==0);
+assert_checkfalse(execstr("[a,b,c]=vectorfind(m,[1 0 1 0],""c"")","errcatch")==0);
+
+// Needle's orientation does not matter:
+assert_checkequal(vectorfind(m, [0 0 1 0], "c"), [2 4 11]);
+assert_checkequal(vectorfind(m, [0 0 1 0]', "c"), [2 4 11]);
+assert_checkequal(vectorfind(m, cat(3, 0,0,1,0), "c"), [2 4 11]);
+assert_checkequal(vectorfind(H, [0 1], "c"), [3 7 16]);
+assert_checkequal(vectorfind(H, [0 1]', "c"), [3 7 16]);
+assert_checkequal(vectorfind(H, cat(3, 0,1), "c"), [3 7 16]);
+
+// Empty needle gets empty result:
+assert_checkequal(vectorfind(m, []), []);
+assert_checkequal(vectorfind(m, [], "c"), []);
+assert_checkequal(vectorfind(H, []), []);
+assert_checkequal(vectorfind(H, [], "c"), []);
+assert_checkequal(vectorfind(H, [], 3), []);
+assert_checkequal(vectorfind(H, [], 4), []);
+
+// Too long needles get empty results:
+assert_checkequal(vectorfind(m, 1:5, "c"), []);   // too tall v
+assert_checkequal(vectorfind(m, 1:16, "r"), []);  // too long v
+assert_checkequal(vectorfind(H, [0 1 0 2], "r"), []);
+assert_checkequal(vectorfind(H, [0 1 0], "c"), []); // size = 2
+assert_checkequal(vectorfind(H, [0 1 2 3], 3), []); // size = 3
+assert_checkequal(vectorfind(H, [0 1 2], 4), []);   // size = 2
+
+// Without joker, the matching array is empty 
+[i,ma] = vectorfind(m, [0 0 1 0], "c");
+assert_checkequal(ma, []);
+[i,ma] = vectorfind(m, [0 0 1 0], "c",,"headIJK");
+assert_checkequal(ma, []);
+
+// ================
+// CHECKING RESULTS
+// ================
+// ====================
+// WITH DECIMAL NUMBERS
+// ====================
+m = [
+//1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+  1  0  0  0  1  0  1  0  1  0  0  1  1  1  1
+  0  0  1  0  0  1  0  1  0  0  0  0  0  0  0
+  0  1  1  1  0  0  1  1  1  0  1  1  0  0  1
+  0  0  1  0  1  0  1  0  1  0  0  0  0  0  1
+  ];
+assert_checkequal(vectorfind(m, [1 1 1 1 0 0 1 1 1 0 1 1 0 0 1]), []);
+assert_checkequal(vectorfind(m, [0 1 1 1 0 0 1 1 1 0 1 1 0 0 1]), 3);
+assert_checkequal(vectorfind(m, [1 0 0 0], "c"), [1 13 14]);
+
+// With %inf
+m(2,2) = %inf;
+assert_checkequal(vectorfind(m, [0 %inf 1 0]), 2);
+
+// With %nan in the haystack
+m(2,2) = %nan;
+assert_checkequal(vectorfind(m, [0 1 1 0], "c"), 8);
+assert_checkequal(vectorfind(m, [%nan 1]), 6);    // Matches as any other value
+
+// With short v
+assert_checkequal(vectorfind(m,[1 0 1],"c"), [25 33 45 57]);
+assert_checkequal(vectorfind(m,[1 1 0 0],"r"), [11 43]);
+
+// Option indType
+assert_checkequal(vectorfind(m, [1 0 0 0], "c"), [1 13 14]);
+assert_checkequal(vectorfind(m, [1 0 0 0], "c",,"headN"), [1 49 53]);
+assert_checkequal(vectorfind(m, [1 0 0 0], "c",,"headIJK"), [1 1 ; 1 13 ; 1 14]);
+assert_checkequal(vectorfind(m, [0 1 1 1 0 0 1 1 1 0 1 1 0 0 1],"r",,"headN"), 3);
+assert_checkequal(vectorfind(m, [0 1 1 1 0 0 1 1 1 0 1 1 0 0 1],"r",,"headIJK"), [3 1]);
+
+// With jokers in the needle
+[ind, ma] = vectorfind(m, [1 -1 -1 0],"c",-1);
+assert_checkequal(ind, [1 12 13 14]);
+assert_checkequal(ma, [1 0 0 0; 1 0 1 0; 1 0 0 0; 1 0 0 0]);
+// With %nan jokers in the needle
+assert_checkequal(vectorfind(m, [1 %nan %nan 0],"c",%nan), [1 12 13 14]);
+
+// With %nan in the haystack, ignored by %nan in the needle
+[ind, ma] = vectorfind(m, [0 %nan 1 0],"c",%nan);
+assert_checkequal(ind, [2 4 8 11]);
+assert_checkequal(ma, [0 %nan 1 0; 0 0 1 0; 0 1 1 0; 0 0 1 0]);
+
+// With %nan jokers in the needle
+assert_checkequal(vectorfind(m,[1 1 %nan 0],"r",%nan), [7 11 27 43]);
+assert_checkequal(vectorfind(m,[0 %nan %nan 0 0 1],"r",%nan), [2 39 40]);
+assert_checkequal(vectorfind(m,[0 %nan 1],"c",%nan), [5 9 13 18 26 29 34 41 58]);
+
+// Hypermatrix
+// ===========
+// Option indType
+    //              dir = "r" = 1
+assert_checkequal(vectorfind(H, [1 0 0]), [1 10 12]);
+assert_checkequal(vectorfind(H, [1 0 0], "r",,"headN"), [1 26 32]);
+res =  [1  1  1  1
+        2  1  2  2
+        2  1  3  2];
+assert_checkequal(vectorfind(H, [1 0 0], "r",,"headIJK"), res);
+    //              dir = "c" = 2
+assert_checkequal(vectorfind(H, [0 1], "c"), [3 7 16]);
+assert_checkequal(vectorfind(H, [0 1], "c",,"headN"), [5 13 31]);
+res =  [1  3  1  1
+        1  1  3  1
+        1  1  3  2];
+assert_checkequal(vectorfind(H, [0 1], "c",,"headIJK"), res);
+    //              dir = 3
+assert_checkequal(vectorfind(H, [0 2 0], 3), [3 7]);
+assert_checkequal(vectorfind(H, [0 2 0], 3,,"headN"), [3 19]);
+res =  [1  2  1  1
+        1  1  1  2];
+assert_checkequal(vectorfind(H, [0 2 0], 3,,"headIJK"), res);
+    //              dir = 4
+assert_checkequal(vectorfind(H, [0 1], 4), [5 8 11 15]);
+assert_checkequal(vectorfind(H, [0 1], 4,,"headN"), [5 8 11 15]);
+res =  [1  3  1  1
+        2  1  2  1
+        1  3  2  1
+        1  2  3  1];
+assert_checkequal(vectorfind(H, [0 1], 4,,"headIJK"), res);
+
+// With short v
+// ------------
+//  H  =
+// (:,:,1,1)
+//    1   0   0
+//    2   2   1
+// (:,:,2,1)
+//    1   2   0
+//    0   0   2
+// (:,:,3,1)
+//    0   0   1
+//    1   0   2
+//
+// (:,:,1,2)
+//    0   2   1
+//    0   1   2
+// (:,:,2,2)
+//    2   2   1
+//    1   0   0
+// (:,:,3,2)
+//    0   1   2
+//    1   0   0
+assert_checkequal(vectorfind(H, [0 1], "r"), [15 20 31]);
+assert_checkequal(vectorfind(H, [0 1], 1  ), [15 20 31]);
+res = [1  2  3  1
+       2  1  1  2
+       1  1  3  2];
+assert_checkequal(vectorfind(H, [0 1], "r",,"headIJK"), res);
+assert_checkequal(vectorfind(H, 2, "c"), [2 4 9 12 18 21 24 25 27 35]);
+
+assert_checkequal(vectorfind(H, [0 0], 3), [5 10 28 30]);
+res = [
+  1  3  1  1
+  2  2  2  1
+  2  2  2  2
+  2  3  2  2];
+assert_checkequal(vectorfind(H, [0 0], 3,, "headIJK"), res);
+H2 = matrix(H,1,3,3,4);
+assert_checkequal(vectorfind(H2, [0 1], 4), [5 8 13 20]);
+res = [
+  1  2  2  1
+  1  2  3  1
+  1  1  2  2
+  1  2  1  3];
+assert_checkequal(vectorfind(H2, [0 1], 4,, "headIJK"), res);
+
+// Additional tests with an hypermatrix haystack
+// ---------------------------------------------
+m = matrix(m,4,5,3);
+m(2,2) = 0;
+//(:,:,1)
+//   1   0   0   0   1
+//   0   0   1   0   0
+//   0   1   1   1   0
+//   0   0   1   0   1
+//(:,:,2)
+//   0   1   0   1   0
+//   1   0   1   0   0
+//   0   1   1   1   0
+//   0   1   0   1   0
+//(:,:,3)
+//   0   1   1   1   1
+//   0   0   0   0   0
+//   1   1   0   0   1
+//   0   0   0   0   1
+assert_checkequal(vectorfind(m, [1 0 1 1], "c"), [7 9 15]); // linearized columns index
+assert_checkequal(vectorfind(m, [0 1 0 1 0], "r"), [5 8]);  // linearized rows index
+
+// Short needle
+// ------------
+    // default indType = headN
+assert_checkequal(vectorfind(m, [1 1 0], "c"), 30);
+assert_checkequal(vectorfind(m, [1 1 1], "r"), [7 27 45 49]);
+assert_checkequal(vectorfind(m, [1 1], 3), [7 10 11 15 25 27 33]);
+    // indType = headIJK
+assert_checkequal(vectorfind(m, [1 1 0], "c",,"headIJK"), [2 3 2]);
+res = [3  2  1
+       3  2  2
+       1  2  3
+       1  3  3];
+assert_checkequal(vectorfind(m, [1 1 1], "r",,"headIJK"), res);
+res = [
+  3  2  1
+  2  3  1
+  3  3  1
+  3  4  1
+  1  2  2
+  3  2  2
+  1  4  2];
+assert_checkequal(vectorfind(m, [1 1], 3,,"headIJK"), res);
+
+// With jokers in the needle:
+// -------------------------
+//  Columns starting and ending with 1:
+[ind, ma] = vectorfind(m, [1 %nan %nan 1], "c", %nan);
+assert_checkequal(ind, [5 7 9 15]);
+assert_checkequal(ma, [1 0 0 1; 1 0 1 1; 1 0 1 1; 1 0 1 1]);
+//  Rows starting and ending with 1:
+assert_checkequal(vectorfind(m, [1 %nan %nan %nan 1], "r", %nan), [1 11]);
+//  Stack starting and ending with 1:
+[ind, ma] = vectorfind(m, [1 %nan 1], 3, %nan);
+assert_checkequal(ind, [7 17 20]);
+assert_checkequal(ma, [1 1 1; 1 0 1; 1 0 1]);
+
+// With jokers in short needle:
+// ---------------------------
+[ind, ma] = vectorfind(m, [1 %nan 1], 2, %nan);
+assert_checkequal(ind, [10 25 33 45 57]);
+assert_checkequal(ma, [1 1 1; 1 0 1; 1 0 1; 1 0 1; 1 0 1]);
+res = [1  2  1
+       3  2  1
+       1  4  1];
+assert_checkequal(vectorfind(m, [%nan 1 1], 3, %nan, "headIJK"), res);
+
+// ===================
+// WITH NUMERIC SPARSE
+// ===================
+m = [
+  0  0  1  1  1
+  1  0  0  2  0
+  2  0  2  2  1];
+m = sparse(m);
+assert_checkequal(vectorfind(m,[0 0 0],"c"), 2);
+assert_checkequal(vectorfind(m,[1 0 0 2 0],"r"), 2);
+// Joker
+[ind, ma] = vectorfind(m,[1 %nan 2],"c", %nan);
+assert_checkequal(ind, [3 4]);
+assert_checkequal(ma, sparse([1 0 2 ; 1 2 2]));
+// Short needle
+assert_checkequal(vectorfind(m,[0 0],"r"), [1 5]);
+// Short needle with joker
+[ind, ma] = vectorfind(m,[0 %nan 2],"r", %nan);
+assert_checkequal(ind, [5 6]);
+assert_checkequal(ma, sparse([0 0 2 ; 0 2 2]));
+
+
+// ==========
+// WITH TEXTS
+// ==========
+m  = [
+// 1    2    3    4    5    6    7    8    9   10   11   12
+  "U"  "C"  "G"  "A"  "A"  "A"  "U"  "U"  "A"  "G"  "A"  "G"
+  "A"  "A"  "A"  "A"  "C"  "C"  "U"  "U"  "C"  "G"  "G"  "G"
+  "A"  "G"  "A"  "C"  "G"  "C"  "C"  "C"  "G"  "C"  "A"  "G"
+  "C"  "U"  "G"  "G"  "G"  "A"  "A"  "G"  "C"  "C"  "C"  "C"
+  "C"  "G"  "G"  "A"  "A"  "G"  "U"  "C"  "A"  "U"  "G"  "C"
+  ];
+// U  C  G  A  A  A  U  U  A  G  A  G
+// A  A  A  A  C  C  U  U  C  G  G  G
+// A  G  A  C  G  C  C  C  G  C  A  G
+// C  U  G  G  G  A  A  G  C  C  C  C
+// C  G  G  A  A  G  U  C  A  U  G  C
+assert_checkequal(vectorfind(m, ["A" "C" "C" "A" "G"], "c"), 6);
+assert_checkequal(vectorfind(m, ["C" "U" "G" "G" "G" "A" "A" "G" "C" "C" "C" "C"],"r"), 4);
+
+// Short needle
+assert_checkequal(vectorfind(m, ["A" "C" "G"], "c"), [17 21 41 53]);
+assert_checkequal(vectorfind(m, ["A" "C" "G"], "r"), 13);
+// With joker
+[ind, ma] = vectorfind(m, ["A" "" "" "" "A"], "c", "");
+assert_checkequal(ind, [4 5 9]);
+assert_checkequal(ma, ["A" "A" "C" "G" "A"; "A" "C" "G" "G" "A"; "A" "C" "G" "C" "A"] );
+// With joker in short needle
+[ind, ma] = vectorfind(m, ["A" "" "U" "" "G"], "r", "");
+assert_checkequal(ind, 26);
+assert_checkequal(ma, ["A" "U" "U" "A" "G"]);
+
+// Text hypermat:
+// -------------
+m = matrix(m,3,5,4);
+// m  =
+//(:,:,1)
+//!U  C  A  G  A  !
+//!A  C  G  G  G  !
+//!A  C  U  A  G  !
+//(:,:,2)
+//!A  G  C  A  C  !
+//!A  A  G  A  A  !
+//!C  A  G  C  G  !
+//(:,:,3)
+//!U  A  U  C  G  !
+//!U  U  C  A  C  !
+//!C  U  G  C  A  !
+//(:,:,4)
+//!G  C  G  G  G  !
+//!G  U  A  G  C  !
+//!C  A  C  G  C  !
+assert_checkequal(vectorfind(m, ["A" "A" "C"], "c"), [6 9]);
+assert_checkequal(vectorfind(m, ["" "G" "G"], "c", ""), [5 8 19]);
+// Joker
+[ind, ma] = vectorfind(m, ["" "G" "G"], "c", "","headN");
+assert_checkequal(ind, [13 22 55]);
+assert_checkequal(ma, ["A" "G" "G"; "C" "G" "G"; "G" "G" "G"]);
+res = [
+  1  2  1
+  1  5  4];
+assert_checkequal(vectorfind(m, ["" "C" "C"], "c", "", "headIJK"), res);
+// Short needle
+res = [
+  1  2  1
+  2  2  1
+  2  5  4];
+assert_checkequal(vectorfind(m, ["C" "C"], "c",,"headIJK"), res);
+// Short needle with joker
+res = [
+  1  3  1
+  2  2  2];
+assert_checkequal(vectorfind(m, ["A" "" "A"],"r","","headIJK"), res);
+
+// =============
+// WITH BOOLEANS
+// =============
+m = asciimat(m(:,:,1:3))<70;
+// m  =
+// (:,:,1)
+//  F T T F T
+//  T T F F F
+//  T T F T F
+// (:,:,2)
+//  T F T T T
+//  T T F T T
+//  T T F T F
+// (:,:,3)
+//  F T F T F
+//  F F T T T
+//  T F F T T
+assert_checkequal(vectorfind(m, [%T %T %T],"c"), [2 6 9 14]);
+// short needle
+assert_checkequal(vectorfind(m, [%T %T %T],"r"), [22 38]);
+res = [
+  1  3  2
+  2  3  3];
+assert_checkequal(vectorfind(m, [%T %T %T],"r",,"headIJK"), res);
+// Joker: Note that v and joker are numerical
+[ind, ma] = vectorfind(m, [0 2 1],"c",2);
+assert_checkequal(ind, [1 4 7 11 15]);
+assert_checkequal(ma, [0 1 1; 0 0 1; 0 1 1; 0 0 1; 0 1 1]==1);
+// Short needle with joker
+res = [
+  1  1  2
+  2  2  2
+  3  1  3];
+assert_checkequal(vectorfind(m, [1 0 2 1],"r",2, "headIJK"), res);
index e09312c..ff4e55f 100644 (file)
             <li><code>twinkle</code> can now blink together several hierarchically independent objects, like a curve and its labels, etc.</li>
             <li><code>repmat</code> is improved: more neutral default frame color; improved labels positioning; colors can now be specified by their predefined name or "#RRGGBB" hexa code; a structure of handles is now returned to easily post-process both subframes and the set of labels.</li>
             <li><code>plot</code> can now work in semi or bi-logarithmic mode with some input logflag.</li>
-            <li><code>v</code> function added.</li>
-            <li>The default smarter grid_style value is now 7 instead of 3.</li>
+            <li><code>plotimplicit</code> function added.</li>
+            </li>The default smarter grid_style value is now 7 instead of 3.</li>
+            <li><code>weekday</code> accepts new date formats and new syntaxes. A language option applying to the day names is now available.</li>
+            <li><code>vectorfind</code> is upgraded:
+                <ul>
+                    <li><code>vectorfind(m, [])</code> now returns <code>[]</code> instead of an error.</li>
+                    <li>A too long needle now returns [] instead of an error.</li>
+                    <li>%nan values never matched. They are now regularly processed, as other values.</li>
+                    <li>A needle shorter than the haystack size can now be used.</li>
+                    <li>A wildcard value matching any value of the haystack can now be specified and used in the needle. Actual matching ranges can then be returned: Options `joker` and `matching` added.</li>
+                    <li>Hypermatrices are now accepted as haystack.</li>
+                    <li>The probing direction can now be numeric: 1, 2, ..</li>
+                    <li>Returned indices can now be formatted with the new option <code>indType</code>.</li>
+                    <li>There were no unit tests. More than 100 tests are added.</li>
+                </ul>
+            </li>
         </ul>
         <h2 class="title">Help pages</h2>
         <ul>
             <li>overhauled/rewritten: <code>bitget, edit, factorial</code></li>
             <li>fixed / improved:  <code>bench_run, M_SWITCH, comet, comet3d</code></li>
+            <li>Rewritten: <code>weekday</code></li>
+            <li>Translations added:
+                <ul>
+                    <li>ru_RU: <code>weekday</code></li>
+                </ul>
+            </li>
         </ul>
 
         <h2 class="title">Bug fixes</h2>