changeset 29168:8a2449d40f3c

cosd.m, sind.m: Extend input to complex inputs. * sind.m: Reword documentation to be clearer. Add input validation to ensure X is numeric. Determine whether X is complex and use different algorithm for real versus complex. Add BIST tests for special values (Inf, NaN). Add BIST tests to verify parity of function. Add BIST test for large value input. Add BIST tests for complex inputs. Add BIST test for input validation. * cosd.m: Reword documentation to be clearer. Add input validation to ensure X is numeric. Add BIST tests for same cases as in sind().
author Rik <rik@octave.org>
date Wed, 09 Dec 2020 19:17:10 -0800
parents 9193e7c990ea
children 3ec3e0a5b69e
files scripts/elfun/cosd.m scripts/elfun/sind.m
diffstat 2 files changed, 43 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/elfun/cosd.m	Wed Dec 09 20:04:59 2020 +0100
+++ b/scripts/elfun/cosd.m	Wed Dec 09 19:17:10 2020 -0800
@@ -27,7 +27,10 @@
 ## @deftypefn {} {} cosd (@var{x})
 ## Compute the cosine for each element of @var{x} in degrees.
 ##
-## Returns zero for elements where @code{(@var{x}-90)/180} is an integer.
+## The function is more accurate than @code{cos} for large values of @var{x}
+## and for multiples of 90 degrees (@code{@var{x} = 90 + 180*n} with n an
+## integer) where @code{cosd} returns 0 rather than a small value on the order
+## of eps.
 ## @seealso{acosd, cos}
 ## @end deftypefn
 
@@ -37,7 +40,11 @@
     print_usage ();
   endif
 
-  ## Advance phase by 90 degrees to turn sin in to cos and use sind. 
+  if (! isnumeric (x))
+    error ("cosd: X must be numeric");
+  endif
+
+  ## Advance phase by 90 degrees to transform sin to cos and use sind().
   y = sind (x + 90);
 
 endfunction
@@ -46,5 +53,11 @@
 %!assert (cosd (10:20:360), cos ([10:20:360] * pi/180), 5*eps)
 %!assert (cosd ([-270, -90, 90, 270]) == 0)
 %!assert (cosd ([-360, -180, 0, 180, 360]), [1, -1, 1, -1, 1])
+%!assert (cosd ([-Inf, NaN, +Inf, 0]), [NaN, NaN, NaN, 1])
+%!assert (cosd (+23) == cosd (-23))
+%!assert (cosd (1e6), 0.17364817766693033, 5*eps)
+%!assert (cosd (90 + 180i), -i*sinh (pi))
+%!assert (cosd (1e6 + 180i), 2.01292156189451577 + 11.3732880565446539i, 5*eps)
 
 %!error <Invalid call> cosd ()
+%!error <X must be numeric> cosd ("abc")
--- a/scripts/elfun/sind.m	Wed Dec 09 20:04:59 2020 +0100
+++ b/scripts/elfun/sind.m	Wed Dec 09 19:17:10 2020 -0800
@@ -27,8 +27,9 @@
 ## @deftypefn {} {} sind (@var{x})
 ## Compute the sine for each element of @var{x} in degrees.
 ##
-## The function is more exact than @code{sin} for multiples of 180 degrees and
-## returns zero rather than a small value on the order of eps.
+## The function is more accurate than @code{sin} for large values of @var{x}
+## and for multiples of 180 degrees (@code{@var{x}/180} is an integer) where
+## @code{sind} returns 0 rather than a small value on the order of eps.
 ## @seealso{asind, sin}
 ## @end deftypefn
 
@@ -38,13 +39,28 @@
     print_usage ();
   endif
 
+  if (! isnumeric (x))
+    error ("sind: X must be numeric");
+  endif
+
+  x_iscomplex = iscomplex (x);
+  if (x_iscomplex)
+    xi = imag (x);
+  endif
+  x = real (x);
+
   ## Wrap multiples so that new domain is [-180, 180)
   x = mod (x-180, 360) - 180;
 
-  ## Integer multiples of pi must be exactly zero
-  x(x == -180) = 0;
-
-  y = sin (x / 180 * pi);
+  if (x_iscomplex)
+    y = sin (complex (x, xi) / 180 * pi);
+    ## Integer multiples of pi must be exactly zero
+    y(x == -180) = complex (0, imag (y(x == -180)));
+  else
+    y = sin (x / 180 * pi);
+    ## Integer multiples of pi must be exactly zero
+    y(x == -180) = 0;
+  endif
 
 endfunction
 
@@ -52,5 +68,11 @@
 %!assert (sind (10:20:360), sin ([10:20:360] * pi/180), 5*eps)
 %!assert (sind ([-360, -180, 0, 180, 360]) == 0)
 %!assert (sind ([-270, -90, 90, 270]), [1, -1, 1, -1])
+%!assert (sind ([-Inf, NaN, +Inf, 0]), [NaN, NaN, NaN, 0])
+%!assert (sind (+23) == -sind (-23))
+%!assert (sind (1e6), -0.984807753012208, 5*eps)
+%!assert (sind (180 + 180i), -i*sinh (pi))
+%!assert (sind (1e6 + 180i), -11.415845458288851 + 2.0054175437381652i, 5*eps)
 
 %!error <Invalid call> sind ()
+%!error <X must be numeric> sind ("abc")