# HG changeset patch # User Rik # Date 1607570230 28800 # Node ID 8a2449d40f3cbbbe07f8af56571962f199927a13 # Parent 9193e7c990ea7fdf80208a817acb332f5553ec18 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(). diff -r 9193e7c990ea -r 8a2449d40f3c scripts/elfun/cosd.m --- 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 cosd () +%!error cosd ("abc") diff -r 9193e7c990ea -r 8a2449d40f3c scripts/elfun/sind.m --- 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 sind () +%!error sind ("abc")