diff libinterp/corefcn/mappers.cc @ 15696:2fac72a256ce

Add complex erf,erfc,erfcx,erfi,dawson routines from Faddeeva package. * libinterp/corefcn/mappers.cc: Add erfi and dawson mapper functions, and add complex-argument test cases for erf, erfc, erfcx, erfi, and dawson. * libinterp/octave-value/ov-base.cc, libinterp/octave-value/ov-base.h: Add erfi and dawson mapper functions. * libinterp/octave-value/ov-complex.cc, libinterp/octave-value/ov-cx-mat.cc, libinterp/octave-value/ov-cx-sparse.cc, libinterp/octave-value/ov-float.cc, libinterp/octave-value/ov-flt-complex.cc, libinterp/octave-value/ov-flt-cx-mat.cc, libinterp/octave-value/ov-flt-re-mat.cc, libinterp/octave-value/ov-re-mat.c, libinterp/octave-value/ov-re-sparse.cc, libinterp/octave-value/ov-scalar.cc, libinterp/octave-value/ov.h: Support erf, erfc, erfcx, erfi, and dawson mapper functions for real and complex matrices and scalars. * liboctave/cruft/Faddeeva/Faddeeva.cc, liboctave/cruft/Faddeeva/Faddeeva.hh: liboctave/cruft/Faddeeva/module.mk, liboctave/cruft/Makefile.am: Add Faddeeva package (from http://ab-initio.mit.edu/Faddeeva) to libcruft, to provide the various complex-argument error functions. * liboctave/numeric/lo-specfun.cc, liboctave/numeric/lo-specfun.h: Add complex-argument erf, erfc, erfcx, erfi, and dawson functions to liboctave API. Delete previous real-argument erfcx implementation in favor of Faddeeva::erfcx (which seems to be slightly faster in gcc/x86-64 benchmarks, with similar accuracy). * doc/interpreter/arith.txi: Include erfi and dawson documentation.
author Steven G. Johnson <stevenj@alum.mit.edu>
date Tue, 27 Nov 2012 23:39:54 -0500
parents 96b7343b8a41
children 7cfb186592de
line wrap: on
line diff
--- a/libinterp/corefcn/mappers.cc	Tue Nov 27 16:38:13 2012 -0800
+++ b/libinterp/corefcn/mappers.cc	Tue Nov 27 23:39:54 2012 -0500
@@ -547,7 +547,7 @@
 @end example\n\
 \n\
 @end ifnottex\n\
-@seealso{erfc, erfcx, erfinv, erfcinv}\n\
+@seealso{erfc, erfcx, erfi, dawson, erfinv, erfcinv}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -584,6 +584,13 @@
 %! assert (erfc (x), 1-v, 1.e-6);
 %! assert (erfinv (v), x, 1.e-6);
 
+%!test
+%! x = [1+2i,-1+2i,1e-6+2e-6i,0+2i];
+%! v = [-0.53664356577857-5.04914370344703i, 0.536643565778565-5.04914370344703i, 0.112837916709965e-5+0.225675833419178e-5i, 18.5648024145755526i];
+%! assert (erf (x), v, -1.e-10);
+%! assert (erf (-x), -v, -1.e-10);
+%! assert (erfc (x), 1-v, -1.e-10);
+
 %!error erf ()
 %!error erf (1, 2)
 */
@@ -596,7 +603,7 @@
 @example\n\
 erf (@var{y}) == @var{x}\n\
 @end example\n\
-@seealso{erf, erfc, erfcx, erfcinv}\n\
+@seealso{erf, erfc, erfcx, erfi, dawson, erfcinv}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -634,7 +641,7 @@
 @example\n\
 erfc (@var{y}) == @var{x}\n\
 @end example\n\
-@seealso{erfc, erf, erfcx, erfinv}\n\
+@seealso{erfc, erf, erfcx, erfi, dawson, erfinv}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -674,7 +681,7 @@
 @ifnottex\n\
 @w{@code{1 - erf (@var{z})}}.\n\
 @end ifnottex\n\
-@seealso{erfcinv, erfcx, erf, erfinv}\n\
+@seealso{erfcinv, erfcx, erfi, dawson, erf, erfinv}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -707,11 +714,11 @@
 @ifnottex\n\
 \n\
 @example\n\
-exp (z^2) * erfc (x)\n\
+exp (z^2) * erfc (z)\n\
 @end example\n\
 \n\
 @end ifnottex\n\
-@seealso{erfc, erf, erfinv, erfcinv}\n\
+@seealso{erfc, erf, erfi, dawson, erfinv, erfcinv}\n\
 @end deftypefn")
 {
   octave_value retval;
@@ -724,12 +731,98 @@
 }
 
 /*
-## FIXME: Need a test for erfcx
+
+%!test
+%! x = [1+2i,-1+2i,1e-6+2e-6i,0+2i];
+%! assert (erfcx (x), exp (x.^2) .* erfc(x), -1.e-10);
+
+%!test
+%! x = [100, 100+20i];
+%! v = [0.0056416137829894329, 0.0054246791754558-0.00108483153786434i];
+%! assert (erfcx (x), v, -1.e-10);
 
 %!error erfcx ()
 %!error erfcx (1, 2)
 */
 
+DEFUN (erfi, args, ,
+    "-*- texinfo -*-\n\
+@deftypefn {Mapping Function} {} erfi (@var{z})\n\
+Compute the imaginary error function,\n\
+@tex\n\
+$$\n\
+ -i {\\rm erf} (iz) \n\
+$$\n\
+@end tex\n\
+@ifnottex\n\
+\n\
+@example\n\
+-i * erf (i*z)\n\
+@end example\n\
+\n\
+@end ifnottex\n\
+@seealso{erfc, erf, erfcx, dawson, erfinv, erfcinv}\n\
+@end deftypefn")
+{
+  octave_value retval;
+  if (args.length () == 1)
+    retval = args(0).erfi ();
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+
+%!test
+%! x = [-0.1, 0.1, 1, 1+2i,-1+2i,1e-6+2e-6i,0+2i];
+%! assert (erfi (x), -i * erf(i*x), -1.e-10);
+
+%!error erfi ()
+%!error erfi (1, 2)
+*/
+
+DEFUN (dawson, args, ,
+    "-*- texinfo -*-\n\
+@deftypefn {Mapping Function} {} dawson (@var{z})\n\
+Compute the Dawson (scaled imaginary error) function,\n\
+@tex\n\
+$$\n\
+ {\\sqrt{\\pi} \\over 2} e^{-z^2} {\\rm erfi} (z) \\equiv -i {\\sqrt{\\pi} \\over 2} e^{-z^2} {\\rm erf} (iz)\n\
+$$\n\
+@end tex\n\
+@ifnottex\n\
+\n\
+@example\n\
+(sqrt (pi) / 2) * exp (-z^2) * erfi (z)\n\
+@end example\n\
+\n\
+@end ifnottex\n\
+@seealso{erfc, erf, erfcx, erfi, erfinv, erfcinv}\n\
+@end deftypefn")
+{
+  octave_value retval;
+  if (args.length () == 1)
+    retval = args(0).dawson ();
+  else
+    print_usage ();
+
+  return retval;
+}
+
+/*
+
+%!test
+%! x = [0.1, 1, 1+2i,-1+2i,1e-4+2e-4i,0+2i];
+%! v = [0.099335992397852861, 0.53807950691, -13.38892731648-11.828715104i, 13.38892731648-11.828715104i, 0.0001000000073333+0.000200000001333i, 48.160012114291i];
+%! assert (dawson (x), v, -1.e-10);
+%! assert (dawson (-x), -v, -1.e-10);
+
+%!error dawson ()
+%!error dawson (1, 2)
+*/
+
 DEFUN (exp, args, ,
     "-*- texinfo -*-\n\
 @deftypefn {Mapping Function} {} exp (@var{x})\n\