changeset 29160:ee20ff0ceb60

sind.m: Overhaul function for improved accuracy with large inputs. * sind.m: More explicitly describe the advantage of sind() in documentation. Unwrap input in to domain [0, 360) which improves accuracy for large arguments. Zero out inputs which are a multiple of 180 degrees before calling sin() function for improved performance. Expand BIST tests.
author Rik <rik@octave.org>
date Mon, 07 Dec 2020 17:32:04 -0800
parents a88f6107aceb
children b58e3a04fab3
files scripts/elfun/sind.m
diffstat 1 files changed, 12 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/elfun/sind.m	Mon Dec 07 13:34:49 2020 -0800
+++ b/scripts/elfun/sind.m	Mon Dec 07 17:32:04 2020 -0800
@@ -27,7 +27,8 @@
 ## @deftypefn {} {} sind (@var{x})
 ## Compute the sine for each element of @var{x} in degrees.
 ##
-## Returns zero for elements where @code{@var{x}/180} is an integer.
+## 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.
 ## @seealso{asind, sin}
 ## @end deftypefn
 
@@ -37,15 +38,19 @@
     print_usage ();
   endif
 
-  I = x / 180;
-  y = sin (I .* pi);
-  y(I == fix (I) & isfinite (I)) = 0;
+  ## Unwrap multiples so that new domain is [0, 360)
+  x = mod (x, 360);
+
+  ## Integer multiples of pi must be exactly zero
+  x(x == 180) = 0;
+
+  y = sin (x / 180 * pi);
 
 endfunction
 
 
-%!assert (sind (10:10:90), sin (pi*[10:10:90]/180), -10*eps)
-%!assert (sind ([0, 180, 360]) == 0)
-%!assert (sind ([90, 270]) != 0)
+%!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])
 
 %!error <Invalid call> sind ()