* Bug 16234 fixed [special_functions]: airy() added 19/21119/11
Samuel GOUGEON [Tue, 5 Nov 2019 14:11:02 +0000 (15:11 +0100)]
  http://bugzilla.scilab.org/16234

  airy() page (PDF): http://bugzilla.scilab.org/attachment.cgi?id=5021

Change-Id: Ib325a40a0c12bf443dfec2cd7b118a4c8dcb9a4d

17 files changed:
scilab/CHANGES.md
scilab/modules/helptools/data/configuration/scilab_macros.txt
scilab/modules/helptools/etc/images_md5.txt
scilab/modules/helptools/images/_LaTeX_airy.xml_1.png [new file with mode: 0644]
scilab/modules/helptools/images/_LaTeX_airy.xml_2.png [new file with mode: 0644]
scilab/modules/helptools/images/_LaTeX_airy.xml_3.png [new file with mode: 0644]
scilab/modules/helptools/images/_LaTeX_airy.xml_4.png [new file with mode: 0644]
scilab/modules/helptools/images/_LaTeX_airy.xml_5.png [new file with mode: 0644]
scilab/modules/helptools/images/_LaTeX_airy.xml_6.png [new file with mode: 0644]
scilab/modules/helptools/images/airy_1.png [new file with mode: 0644]
scilab/modules/helptools/images/airy_2.png [new file with mode: 0644]
scilab/modules/helptools/images/airy_z_numbers.png [new file with mode: 0644]
scilab/modules/m2sci/macros/kernel/not_yet_converted.sci
scilab/modules/special_functions/help/en_US/airy.xml [new file with mode: 0644]
scilab/modules/special_functions/macros/airy.sci [new file with mode: 0644]
scilab/modules/special_functions/tests/unit_tests/airy.tst [new file with mode: 0644]
scilab/modules/special_functions/tests/unit_tests/airy_complex.sod.ref [new file with mode: 0644]

index 612224f..3729e5b 100644 (file)
@@ -83,6 +83,7 @@ Packaging & Supported Operating Systems
 Feature changes and additions
 -----------------------------
 
+* `airy()` is added: Evaluation of Airy functions of the first and second kind, and their first derivative, possibly scaled.
 * Empty strings are used as the default values on String allocation
 * HTTP get, post, put, upload, patch, delete functions added
 * JSON encoding / decoding for Scilab datatypes added
@@ -304,6 +305,7 @@ Bug Fixes
 * [#16210](http://bugzilla.scilab.org/show_bug.cgi?id=16210): The uicontrol.units = "normalized" property was not described.
 * [#16227](http://bugzilla.scilab.org/show_bug.cgi?id=16227): `WSCI` was not defined as environment variable and could not be used as `%WSCI%` in commands sent with `host()` or `unix_*()`.
 * [#16230](http://bugzilla.scilab.org/show_bug.cgi?id=16230): `MSWin>scilab --help` missed displaying some options like `-args..`, `-noatomsautoload`, etc.
+* [#16234](http://bugzilla.scilab.org/show_bug.cgi?id=16234): Airy functions were not available.
 * [#16242](http://bugzilla.scilab.org/show_bug.cgi?id=16242): `loadmatfile()` could not read Octave native text data files.
 * [#16245](http://bugzilla.scilab.org/show_bug.cgi?id=16245): `gsort` could not sort booleans.
 * [#16246](http://bugzilla.scilab.org/show_bug.cgi?id=16246): `isvector` was broken for sparse matrices.
index ed7d9fb..61ef1ce 100644 (file)
@@ -234,6 +234,12 @@ _LaTeX_QUANT_f.xml_2.png=9ab0347369b93587a1fc8dbd6c6a8862
 _LaTeX_RAMP.xml_1.png=c851aba90cb36bc4a4d869245c01a167
 _LaTeX_SAWTOOTH_f.xml_1.png=d2352f773be10a7110da96a1bf7f316d
 _LaTeX_STEP_FUNCTION.xml_1.png=7544adffd057978d0ddaed767ae05f25
+_LaTeX_airy.xml_1.png=85ada28a038e551dea516e0780f5d194
+_LaTeX_airy.xml_2.png=0ba7125fa8926afbd65815644153c697
+_LaTeX_airy.xml_3.png=ed25f7735385d7115b62c030b29c9b63
+_LaTeX_airy.xml_4.png=dd21759b389fa8497108d7ffa2b93448
+_LaTeX_airy.xml_5.png=24e27ac7cb803a2c15a19e7fe81cd0fa
+_LaTeX_airy.xml_6.png=99b138cc89d2519f769a3fa07261a4e0
 _LaTeX_assert_computedigits.xml_1.png=082a70de2c216b6eb1951a75720fdcfc
 _LaTeX_assert_computedigits.xml_2.png=27dba5ee1401d31d2106736651e99140
 _LaTeX_blockdiag.xml_1.png=26bcad469ac051064707c071f102456c
@@ -453,6 +459,8 @@ acsc_1.png=4fd05d7d355266d821063c9a6c26abb0
 acscd_1.png=6e599765c5f8d0e189002d51f2d9068a
 acsch_1.png=15259a5eaa158abd0fd70e05b27d69eb
 addcolor_1.png=7e5f272c2700aafbd41da8efd8e9d8eb
+airy_1.png=4a046e9854c5d1b761d532acfa45296b
+airy_2.png=bcbcd5ee1de18b8202b2208b1f10971c
 analpf_1.png=6d59d9510e91abd50fcfd04a4b129d93
 analyze_1.png=f618685a506715b35493fcc61fe78a25
 arl2_1.png=08f7b10fe894dbb9e21a4f965de0fe07
diff --git a/scilab/modules/helptools/images/_LaTeX_airy.xml_1.png b/scilab/modules/helptools/images/_LaTeX_airy.xml_1.png
new file mode 100644 (file)
index 0000000..eab8468
Binary files /dev/null and b/scilab/modules/helptools/images/_LaTeX_airy.xml_1.png differ
diff --git a/scilab/modules/helptools/images/_LaTeX_airy.xml_2.png b/scilab/modules/helptools/images/_LaTeX_airy.xml_2.png
new file mode 100644 (file)
index 0000000..92267e0
Binary files /dev/null and b/scilab/modules/helptools/images/_LaTeX_airy.xml_2.png differ
diff --git a/scilab/modules/helptools/images/_LaTeX_airy.xml_3.png b/scilab/modules/helptools/images/_LaTeX_airy.xml_3.png
new file mode 100644 (file)
index 0000000..e20ca0c
Binary files /dev/null and b/scilab/modules/helptools/images/_LaTeX_airy.xml_3.png differ
diff --git a/scilab/modules/helptools/images/_LaTeX_airy.xml_4.png b/scilab/modules/helptools/images/_LaTeX_airy.xml_4.png
new file mode 100644 (file)
index 0000000..cb299a0
Binary files /dev/null and b/scilab/modules/helptools/images/_LaTeX_airy.xml_4.png differ
diff --git a/scilab/modules/helptools/images/_LaTeX_airy.xml_5.png b/scilab/modules/helptools/images/_LaTeX_airy.xml_5.png
new file mode 100644 (file)
index 0000000..6ad27b6
Binary files /dev/null and b/scilab/modules/helptools/images/_LaTeX_airy.xml_5.png differ
diff --git a/scilab/modules/helptools/images/_LaTeX_airy.xml_6.png b/scilab/modules/helptools/images/_LaTeX_airy.xml_6.png
new file mode 100644 (file)
index 0000000..4f43c40
Binary files /dev/null and b/scilab/modules/helptools/images/_LaTeX_airy.xml_6.png differ
diff --git a/scilab/modules/helptools/images/airy_1.png b/scilab/modules/helptools/images/airy_1.png
new file mode 100644 (file)
index 0000000..6a2ba8c
Binary files /dev/null and b/scilab/modules/helptools/images/airy_1.png differ
diff --git a/scilab/modules/helptools/images/airy_2.png b/scilab/modules/helptools/images/airy_2.png
new file mode 100644 (file)
index 0000000..429e7d7
Binary files /dev/null and b/scilab/modules/helptools/images/airy_2.png differ
diff --git a/scilab/modules/helptools/images/airy_z_numbers.png b/scilab/modules/helptools/images/airy_z_numbers.png
new file mode 100644 (file)
index 0000000..f45f79a
Binary files /dev/null and b/scilab/modules/helptools/images/airy_z_numbers.png differ
index e9799d5..0c84b1b 100644 (file)
@@ -23,7 +23,6 @@ function allnames=not_yet_converted()
     "addsubplot";
     "addtodate";
     "airfoil";
-    "airy";
     "align";
     "alim";
     "allchild";
diff --git a/scilab/modules/special_functions/help/en_US/airy.xml b/scilab/modules/special_functions/help/en_US/airy.xml
new file mode 100644 (file)
index 0000000..94c9313
--- /dev/null
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2019 - Samuel GOUGEON - Le Mans Université
+ *
+ * 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:mml="http://www.w3.org/1998/Math/MathML"
+        xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org"
+        xml:lang="en" xml:id="airy">
+    <refnamediv>
+        <refname>airy</refname>
+        <refpurpose>
+            Airy functions of the first and second kind, and their derivatives
+        </refpurpose>
+    </refnamediv>
+    <refsynopsisdiv>
+        <title>Syntax</title>
+        <synopsis>
+            a = airy(z)
+            a = airy(fun, z)
+            a = airy(fun, z, scaled)
+        </synopsis>
+    </refsynopsisdiv>
+    <refsection>
+        <title>Arguments</title>
+        <variablelist>
+            <varlistentry>
+                <term>z</term>
+                <listitem>
+                    array of decimal or complex numbers of any size, from scalr to hypermatrix.
+                </listitem>
+                <para/>
+            </varlistentry>
+            <varlistentry>
+                <term>fun</term>
+                <listitem>
+                    Selected Airy function to evaluate. It can be either a string among
+                    "Ai" "dAi" "Bi" "dBi", or an equivalent integer in [0, 3] (for compatibility
+                    with Octave and Julia)
+                    <table>
+                        <tr><td colspan="2" align="center"><emphasis role="bold">fun</emphasis></td>
+                            <td><emphasis role="bold">Description</emphasis></td></tr>
+                        <tr><td>0</td><td>"Ai"</td><td>Airy function of the first kind (default)</td></tr>
+                        <tr><td>1</td><td>"dAi"</td><td>Derivative Ai' of Ai</td></tr>
+                        <tr><td>2</td><td>"Bi"</td><td>Airy function of the second kind</td></tr>
+                        <tr><td>3</td><td>"dBi"</td><td>Derivative Bi' of Bi</td></tr>
+                    </table>
+                    <para/>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>scaled</term>
+                <listitem>
+                    Single boolean or integer 0|1. Default %F. When <varname>scaled</varname> is
+                    %T or set to 1, the raw result is scaled by the following factors before
+                    being returned:
+                    <table>
+                        <tr style="white-space:nowrap"><td valign="bottom">Ai, dAi : </td>
+                            <td valign="top"><latex fontsize="15" alt="exp(z^1.5 * 2/3)">
+                                    exp\left(2\,z^{3/2}/ 3\right)
+                                </latex>
+                            </td>
+                            <td>      </td>
+                            <td valign="bottom">Bi, dBi : </td>
+                            <td valign="top"><latex fontsize="15" alt="exp(-|real(z^1.5)| * 2/3)">
+                                    exp\left(-2\left|{\mathrm Re}\!\left(z^{3/2}\right)\right|/ 3\right)
+                                </latex>
+                            </td>
+                        </tr>
+                    </table>
+                </listitem>
+            </varlistentry>
+        </variablelist>
+    </refsection>
+    <refsection>
+        <title>Description</title>
+        <para>
+            For a real <emphasis>x</emphasis> variable, the Airy functions of the first and
+            second kind -- respectively Ai(x) and Bi(x) -- are independent real solutions
+            <emphasis>y(x)</emphasis> of the Airy differential equation
+            <emphasis>y'' = x.y</emphasis>. They are defined as the convergent integrals
+            <latex style="display" alt="Ai(x) = 1/π \int_0^∞ cos(t^3/3 + xt) dt">
+                Ai(x) = {1 \over \pi} \int_0^\infty cos\left({t^3 \over 3} + xt\right)dt
+            </latex>
+            and
+            <latex style="display" alt="Bi(x) = 1/π \int_0^∞ [sin(t^3/3 + xt) + exp(-t^3/3 + xt)] dt">
+                Bi(x) = {1 \over \pi} \int_0^\infty
+                \left[ sin\left({t^3 \over 3} + xt\right) + exp\left(- {t^3 \over 3} + xt\right)\right] dt
+            </latex>
+        </para>
+        <para>
+            These definitions can be extended to the complex plane, for any <emphasis>z</emphasis>
+            complex variable, as
+            <latex style="display" fontsize="20" alt="Ai(z) = 1/2π \int_R exp(i(t^3/3 + zt)) dt">
+                Ai(z) = {1 \over 2\pi} \int_{-\infty}^\infty e^{i\left({t^3 \over 3} + zt\right)}dt
+            </latex>
+        </para>
+        <para>
+            Let us note the properties
+            <latex style="display" alt="Ai(z´)=Ai(z)´  Bi(z´)=Bi(z)´ with z´ the complex conjugate.">
+                Ai(\overline z) = \overline{Ai(z)} \quad Bi(\overline z) = \overline{Bi(z)} \quad
+                Ai'(\overline z) = \overline{Ai'(z)} \quad Bi'(\overline z) = \overline{Bi'(z)}
+            </latex>
+        </para>
+        <para>
+            In Scilab, Ai, Bi, and their first derivative are computed through Bessel and gamma
+            functions.
+        </para>
+    </refsection>
+    <refsection>
+        <title>Examples</title>
+        <para>
+            With real numbers
+        </para>
+        <programlisting role="example"><![CDATA[
+x = -10:0.05:3;
+clf
+drawlater
+
+subplot(2,1,1)  // Ai, Bi
+plot(x, airy(x), "b", x, airy(2,x), "r")
+gca().margins(4) = 0.08;
+gca().data_bounds(3:4) = [-0.5 1.25];
+gca().tight_limits = "on";
+xgrid(color("grey60"),1,7)
+legend(["Ai(x)" "Bi(x)"],"in_upper_left")
+title("Airy functions", "fontsize", 3)
+
+subplot(2,1,2)  // Derivatives
+plot(x, airy(1, x), "b", x, airy(3,x), "r")
+legend(["Ai''(x)" "Bi''(x)"],"in_upper_left")
+xlabel("x", "fontsize", 3)
+gca().margins(3) = 0.08;
+gca().x_location = "top";
+gca().x_ticks.labels = emptystr(gca().x_ticks.labels);
+gca().data_bounds(3:4) = [-1 2.5];
+gca().tight_limits = "on";
+xgrid(color("grey60"),1,7)
+
+drawnow
+      ]]></programlisting>
+        <scilab:image><![CDATA[
+x = -10:0.05:3;
+clf
+drawlater
+
+subplot(2,1,1)  // Ai, Bi
+plot(x, airy(x), "b", x, airy(2,x), "r")
+gca().margins(4) = 0.08;
+gca().data_bounds(3:4) = [-0.5 1.25];
+gca().tight_limits = "on";
+xgrid(color("grey60"),1,7)
+legend(["Ai(x)" "Bi(x)"],"in_upper_left")
+title("Airy functions", "fontsize", 3)
+
+subplot(2,1,2)  // Derivatives
+plot(x, airy(1, x), "b", x, airy(3,x), "r")
+legend(["Ai''(x)" "Bi''(x)"],"in_upper_left")
+xlabel("x", "fontsize", 3)
+gca().margins(3) = 0.08;
+gca().x_location = "top";
+gca().x_ticks.labels = emptystr(gca().x_ticks.labels);
+gca().data_bounds(3:4) = [-1 2.5];
+gca().tight_limits = "on";
+xgrid(color("grey60"),1,7)
+
+drawnow
+        ]]></scilab:image>
+        <para/>
+        <para>
+            With scaling
+        </para>
+        <programlisting role="example"><![CDATA[
+x = -10:0.05:3;
+clf
+drawlater
+
+subplot(2,1,1)  // Ai, Ai scaled
+plot(x, airy("Ai",x), x, airy("Ai",x, %t), "color", ["blue" "cyan"])
+gca().margins(4) = 0.08;
+gca().data_bounds(3:4) = [-0.5 1];
+gca().tight_limits = "on";
+xgrid(color("grey60"),1,7)
+legend(["Ai(x)" "Ai(x) scaled"],"in_upper_left")
+title("Airy functions raw vs scaled", "fontsize", 3)
+
+subplot(2,1,2)  // Bi, Bi scaled
+plot(x, airy("Bi", x), x, airy("Bi",x, %t), "color", ["red" "darkorange"])
+legend(["Bi(x)" "Bi(x) scaled"],"in_upper_left")
+xlabel("x", "fontsize", 3)
+gca().margins(3) = 0.08;
+gca().x_location = "top";
+gca().x_ticks.labels = emptystr(gca().x_ticks.labels);
+gca().data_bounds(3:4) = [-0.5 1.5];
+gca().tight_limits = "on";
+xgrid(color("grey60"),1,7)
+
+gcf().children.children.children.thickness = 2;
+drawnow
+      ]]></programlisting>
+        <scilab:image><![CDATA[
+            x = -10:0.05:3;
+            clf
+            drawlater
+
+            subplot(2,1,1)  // Ai, Ai scaled
+            plot(x, airy("Ai",x), x, airy("Ai",x, %t), "color", ["blue" "cyan"])
+            gca().margins(4) = 0.08;
+            gca().data_bounds(3:4) = [-0.5 1];
+            gca().tight_limits = "on";
+            xgrid(color("grey60"),1,7)
+            legend(["Ai(x)" "Ai(x) scaled"],"in_upper_left")
+            title("Airy functions raw vs scaled", "fontsize", 3)
+
+            subplot(2,1,2)  // Bi, Bi scaled
+            plot(x, airy("Bi", x), x, airy("Bi",x, %t), "color", ["red" "darkorange"])
+            legend(["Bi(x)" "Bi(x) scaled"],"in_upper_left")
+            xlabel("x", "fontsize", 3)
+            gca().margins(3) = 0.08;
+            gca().x_location = "top";
+            gca().x_ticks.labels = emptystr(gca().x_ticks.labels);
+            gca().data_bounds(3:4) = [-0.5 1.5];
+            gca().tight_limits = "on";
+            xgrid(color("grey60"),1,7)
+
+            gcf().children.children.children.thickness = 2;
+            gcf().axes_size = [600 570];
+            drawnow
+        ]]></scilab:image>
+        <para>
+            With complex numbers
+        </para>
+        <programlisting role="example"><![CDATA[
+// Initializations
+x = -4.5:0.2:2.5;
+y = -3.5:0.2:3.5;
+[X, Y] = meshgrid(x, y);
+xph = -4.5:0.05:2.5;
+yph = -3.5:0.05:3.5;
+[Xph, Yph] = meshgrid(xph, yph);
+clf
+fig = gcf();
+drawlater
+[nc, cmin] = (100, 15);
+fig.color_map = [0.6 0.6 0.6; jetcolormap(nc-1)];
+meshColor = 1; // grey60 will be used for the mesh color
+if ~isDocked(fig) then
+    fig.axes_size = [800 600];
+end
+fr = 0.55;
+
+
+// |Ai|
+xsetech([0 0 0.5 fr])
+Z = X + %i*Y;
+Z = airy(Z);
+V = abs(Z);
+[smin, smax] = (0, 5);
+surf(x, y, V)
+S = gce();
+set(S, "color_flag",3, "color_mode",1, ..
+       "cdata_mapping","direct", "foreground",meshColor);
+c = S.data.color;
+c = cmin + (nc-cmin)*(c-smin)/(smax-smin);
+S.data.color = c;
+gca().zoom_box = [min(x) min(y) max(x) max(y) smin smax];
+gca().rotation_angles = [47 -60];
+xtitle("", "real(z)","imag(z)", "")
+title("| Ai(z) |", "fontsize",3)
+colorbar(smin, smax, [2, nc])
+
+// arg(Ai)
+xsetech([0 fr 0.5 (1-fr)])
+Z = airy(Xph + %i*Yph);
+V = atan(imag(Z),real(Z));
+grayplot(xph, yph, V.')
+xtitle("","real(z)", "imag(z)")
+title("arg( Ai(z) )", "fontsize", 3)
+gca().tight_limits = "on";
+isoview
+colorbar(,,[2 nc])
+title(fig.children(1), "[rad]")
+
+
+// |Bi|
+xsetech([0.50 0 0.5 fr])
+Z = X + %i*Y;
+Z = airy(2, Z);
+V = abs(Z);
+[smin, smax] = (0, 5);
+surf(x, y, V)
+S = gce();
+set(S, "color_flag",3, "color_mode",1, ..
+       "cdata_mapping","direct", "foreground",meshColor);
+c = S.data.color;
+c = cmin + (nc-cmin)*(c-smin)/(smax-smin);
+S.data.color = c;
+gca().zoom_box = [min(x) min(y) max(x) max(y) smin smax];
+gca().rotation_angles = [40 -130];
+xtitle("", "real(z)","imag(z)", "")
+title("| Bi(z) |", "fontsize",3)
+colorbar(smin, smax, [2, nc])
+
+// arg(Bi)
+xsetech([0.5 fr 0.5 (1-fr)])
+Z = airy(3, Xph + %i*Yph);
+V = atan(imag(Z),real(Z));
+grayplot(xph, yph, V.')
+xtitle("","real(z)", "imag(z)")
+title("arg( Bi(z) )", "fontsize", 3)
+gca().tight_limits = "on";
+isoview
+colorbar(,,[2 nc])
+title(fig.children(1), "[rad]")
+
+drawnow
+      ]]></programlisting>
+        <inlinemediaobject>
+            <imageobject>
+                <imagedata fileref="../../../helptools/images/airy_z_numbers.png"  valign="middle"/>
+                <!--
+                <imagedata fileref="../images/airy_z_numbers.png"  valign="middle"/>
+                -->
+            </imageobject>
+        </inlinemediaobject>
+        <!-- The same automated image is poorer and 2.5x bigger (150kB instead of 61kB)
+      <scilab:image><![CDATA[
+]]></scilab:image>
+        -->
+    </refsection>
+    <refsection role="see also">
+        <title>See also</title>
+        <simplelist type="inline">
+            <member>
+                <link linkend="besseli">besseli</link>
+            </member>
+            <member>
+                <link linkend="besselj">besselj</link>
+            </member>
+            <member>
+                <link linkend="gamma">gamma</link>
+            </member>
+        </simplelist>
+    </refsection>
+    <refsection>
+        <title>History</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.1.0</revnumber>
+                <revremark>
+                    <literal>airy()</literal> introduced.
+                </revremark>
+            </revision>
+        </revhistory>
+    </refsection>
+</refentry>
\ No newline at end of file
diff --git a/scilab/modules/special_functions/macros/airy.sci b/scilab/modules/special_functions/macros/airy.sci
new file mode 100644 (file)
index 0000000..d0b54f1
--- /dev/null
@@ -0,0 +1,110 @@
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2019 - Samuel GOUGEON - Le Mans Université
+//
+// 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.
+
+function y = airy(k, z, scaled)
+
+    fname = "airy"
+
+    // CHECKING INPUT ARGUMENTS
+    // ------------------------
+    rhs = argn(2)
+    select rhs
+    case 1
+        z = k
+        k = 0
+        scaled = %f
+    case 2
+        scaled = %f
+    case 3
+        if ~isdef("scaled","l")
+            scaled = %f
+        else
+            scaled = ~(~scaled)
+        end
+    else
+        msg = _("%s: Wrong number of input arguments: %d to %d expected.\n")
+        error(msprintf(msg, fname, 1, 3))
+    end
+
+    // k
+    if and(type(k) <> [1 8 10]) then
+        msg = _("%s: Argument #%d: Integer number or string expected.\n")
+        error(msprintf(msg, fname, 1))
+    end
+    if type(k)==10 then
+        k = convstr(k(1))
+        k = find(k==["ai" "dai" "bi" "dbi"])
+        if k <> []
+            k = k - 1
+        end
+    else
+        k = real(k(1))
+    end
+    if and(k <> [0:3]) then
+        msg = _("%s: Argument #%d: Must be in the set {%s}.\n")
+        error(msprintf(msg, fname, 1, """Ai"",""Bi"",""dAi"",""dBi"",0,1,2,3"))
+    end
+    // z
+    if type(z) <> 1 then
+        msg = _("%s: Argument #%d: Decimal or complex number expected.\n")
+        error(msprintf(msg, fname, min(rhs,2)))
+    end
+    // Hypermatrices: reshape for bessel*()
+    s = size(z)
+    if length(s) > 2 then
+        z = z(:)
+    end
+
+    // PROCESSING
+    // ----------
+    y = z
+    p = real(z)>0
+    n = ~p
+    zeta(p) = 2/3*(z(p).^1.5)
+    zeta(n) = 2/3*((-z(n)).^1.5)
+
+    select k
+    case 0 // Ai : OK
+        y(p) = sqrt(z(p)/3)/%pi .* besselk(1/3, zeta(p))
+        y(n) = sqrt(-z(n)/9) .* (besselj(1/3, zeta(n)) + besselj(-1/3,zeta(n)))
+        y(z==0) = 1 / (3^(2/3) * gamma(2/3))
+
+    case 1  // Ai' : OK
+        y(p) = -z(p)/(%pi*sqrt(3)) .* besselk(2/3, zeta(p))
+        y(n) =  z(n)/3 .* (besselj(-2/3, zeta(n)) - besselj(2/3,zeta(n)))
+        y(z==0) = -1 / (3^(1/3) * gamma(1/3))
+
+    case 2  // Bi : OK
+        y(p) =   sqrt(z(p)/3) .* (besseli(1/3, zeta(p)) + besseli(-1/3, zeta(p)))
+        y(n) = - sqrt(-z(n)/3) .* (besselj(1/3, zeta(n)) - besselj(-1/3, zeta(n)))
+        y(z==0) = 1 / (3^(1/6) * gamma(2/3))
+
+    case 3  // Bi' : OK
+        y(p) =  z(p)/sqrt(3) .* (besseli(2/3, zeta(p)) + besseli(-2/3, zeta(p)))
+        y(n) = -z(n)/sqrt(3) .* (besselj(2/3, zeta(n)) + besselj(-2/3,zeta(n)))
+        y(z==0) = 3^(1/6) / gamma(1/3)
+    end
+
+    // Scaling
+    // -------
+    if scaled then
+        if k < 2
+            y =  y .* exp(2/3 * z.^1.5);
+        else
+            y = y .* exp(- 2/3 * abs(real(z.^1.5)));
+        end
+    end
+
+    // Reshape the result
+    // ------------------
+    if length(s)>2 then
+        y = matrix(y, s)
+    end
+endfunction
diff --git a/scilab/modules/special_functions/tests/unit_tests/airy.tst b/scilab/modules/special_functions/tests/unit_tests/airy.tst
new file mode 100644 (file)
index 0000000..ffb0fa7
--- /dev/null
@@ -0,0 +1,100 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2019 - Samuel GOUGEON - Le Mans Université
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+// <-- ENGLISH IMPOSED -->
+// ------------------------------
+// unit tests of airy() functions
+// ------------------------------
+
+// Check the result's size:
+for o = list([], -3, rand(1,10), rand(10,1), rand(10,12), rand(3,4,2))
+    assert_checkequal(size(airy(o)), size(o));
+end
+
+// With decimal numbers
+// --------------------
+// Checking values for z=0
+// Ref data out of  W o l f r a m alpha
+// Ai, Ai', Bi, Bi'
+ref = [0.35502805388781724 -0.25881940379280680 0.61492662744600073 0.44828835735382636];
+for k = 0:3
+    assert_checkalmostequal(airy(k,0), ref(k+1), %eps);
+end
+
+// Checking values around 0
+m = 10^(-1:-3:-150)';
+m = [m -m];
+
+// Other values
+// Ref data out of  O c t a v e, checked up to rtol=1e-16 against W o l f r a m
+// alpha for ~20 values sampled among all.
+u = logspace(-10,7,18);
+NaN = %nan; Inf = %inf;
+AiRef =  [0.3550280538619353  0.3550280536289978  0.3550280512996231  0.3550280280058769  0.3550277950684134  0.3550254656937794  0.3550021719474971  0.3547692345431742  0.3524399188055506  0.329203129943538  0.1352924163128814  0.0000000001104753  0.   0.   0.   0.   0.   0.];
+dAiRef = [-0.2588194037928068  -0.2588194037928068  -0.2588194037928068  -0.258819403792805  -0.2588194037926293  -0.2588194037750556  -0.2588194020177528  -0.258819226365053  -0.2588017386620673  -0.2571304219075862  -0.1591474412967932  -0.0000000003520634   0.   0.   0.   0.   0.   0.];
+BiRef = [0.6149266274908295  0.6149266278942891  0.6149266319288842  0.6149266722748364  0.614927075734358  0.6149311103295744  0.6149714562818387  0.6153749159058796  0.6194096138808873  0.6598616901941892  1.2074235949528711  455641153.54823458  6.04122399667D+288  Inf  Inf  Inf  Inf  Inf];
+dBiRef = [0.4482883573538264  0.4482883573538264  0.4482883573538264  0.4482883573538294  0.4482883573541339  0.448288357384573  0.4482883604286089  0.4482886649665696  0.4483192531167072  0.4515126311496465  0.9324359333927754  1429236134.4828949  6.03971274531D+289  Inf  Inf  Inf  Inf  Inf];
+AiScaledRef = [0.3550280538619355  0.3550280536290053  0.3550280512998598  0.3550280280133615  0.3550277953050986  0.3550254731783735   0.3550024086156907  0.3547767138141784  0.3526749570888103  0.3362170143618417  0.2635136447491401  0.1581236668543461  0.0891969209363304 ..
+ 0.0501641707499709  0.0282094762389028  0.0158633558512873  0.0089206205798346  0.];
+dAiScaledRef = [-0.258819403792807  -0.2588194037928123  -0.2588194037929794  -0.2588194037982614  -0.2588194039651756  -0.2588194092314478  -0.2588195745640783  -0.2588246828109525  -0.2589743306787886  -0.2626087509259002  -0.3099768889605148  -0.5039093607113109  -0.8921920625040315  ..
+ -1.586342905829885  -2.820948329126741  -5.0164336220411077  -8.9206205820647817  0.];
+BiScaledRef = [ 0.614926627490829  0.6149266278942761  0.6149266319284743  0.6149266722618727  0.6149270753244066   0.6149310973656884  0.6149710463010045  0.6153619428003007  0.618996811754298   0.6460961952031843  0.6199119435726785  0.3183401053367412  0.1784310111708354  ..
+0.1003290024731052  0.0564189642317552  0.0317267119115927  0.0178412411633862  0.];
+dBiScaledRef = [ 0.4482883573538261  0.4482883573538169  0.4482883573535276  0.4482883573443787  0.4482883570552749  0.4482883479338247  0.4482880615698016  0.4482792143113184  0.4480204732189945  0.4420935438547972  0.4787285706049846  0.9985559426738586  1.783863754962809  ..
+ 3.1726565491304131  5.6418950127005294  10.03286715154597  17.841241158925861  0.];
+Ref = list(AiRef, dAiRef, BiRef, dBiRef, AiScaledRef, dAiScaledRef, BiScaledRef, dBiScaledRef);
+i = 1;
+for scaled = 0:1
+    for k = ["Ai" "dAi" "Bi" "dBi"]
+        tmp = airy(k, u, scaled);
+        ref = Ref(i);
+        j = find(~isinf(ref) & ~isinf(tmp) & ~isnan(tmp));
+        assert_checkalmostequal(tmp(j), ref(j), 500*%eps, 1e-16);
+        i = i + 1;
+    end
+end
+
+// With Complex numbers
+// --------------------
+// Check the property airy(k, z') = airy(k, z)'
+m = rand(10,10);
+z = (m-0.7)*10 + (m'-0.5)*10*%i;
+for k = 0:3
+    assert_checkalmostequal(airy(k,z'), airy(k,z)', 1e-13);
+end
+
+// Check some values, on concentric circles around 0
+r = 10.^(-17:0);            // modulus
+a = (0:30:359)/180*%pi;     // argument
+[A, R] = meshgrid(a,r);
+Z = R.*exp(%i*A);
+load(SCI+"/modules/special_functions/tests/unit_tests/airy_complex.sod.ref");
+// Ref data out of  O c t a v e, checked up to rtol=1e-16 against W o l f r a m
+// alpha for ~10 values sampled among all.
+ref = cat(3,AiRef,dAiRef,BiRef,dBiRef,AiRefScaled,dAiRefScaled,BiRefScaled,dBiRefScaled);
+i = 1;
+for scaled = 0:1
+    for k = ["Ai" "dAi" "Bi" "dBi"]
+        tmp = airy(k, Z, scaled);
+        assert_checkalmostequal(tmp, ref(:,:,i), 50*%eps, 5e-16);
+        i = i + 1;
+    end
+end
+
+// Check error messages
+// --------------------
+assert_checkerror("airy()", "airy: Wrong number of input arguments: 1 to 3 expected.");
+assert_checkerror("airy(1,2,1,4)", "Wrong number of input arguments.");
+assert_checkerror("airy(%z)", "airy: Argument #1: Decimal or complex number expected.");
+assert_checkerror("airy(sparse(1:4))", "airy: Argument #1: Decimal or complex number expected.");
+assert_checkerror("airy(%z,3)", "airy: Argument #1: Integer number or string expected.");
+msg = "airy: Argument #1: Must be in the set {""Ai"",""Bi"",""dAi"",""dBi"",0,1,2,3}.";
+assert_checkerror("airy(-1,3)", msg);
+assert_checkerror("airy(4,3)", msg);
+assert_checkerror("airy(1.5,3)", msg);
+assert_checkerror("airy(""Ci"",3)", msg);
diff --git a/scilab/modules/special_functions/tests/unit_tests/airy_complex.sod.ref b/scilab/modules/special_functions/tests/unit_tests/airy_complex.sod.ref
new file mode 100644 (file)
index 0000000..6cfa037
Binary files /dev/null and b/scilab/modules/special_functions/tests/unit_tests/airy_complex.sod.ref differ