Re: [PATCH v2 guile-lib] src: (math trigonometry): Add it.
Maxime Devos <[email protected]> Mon, 17 Feb 2025 12:05:47 +0100
| Newsgroups | gmane.lisp.guile.devel |
|---|---|
| Message-ID | <[email protected]> |
On 17/02/2025 8:03, Adam Faiz wrote:
> + (cond ((zero? x)
> + (let ((sign (if (positive? y) + -)))
> + (sign 90)))
atan(0,0) is not well-defined (more precisely, there is no unique choice
within the interval [0,360°)) - if the point (0,0) is written in polar
coordinates (0*cos theta, 0*sin theta), then any angle theta can be used.
If you intend to support (arctan2 0 0), it may be good to mention that
in the docstring, and make sure it is in {0,180,-180} to match IEEE, and
add a test for x=y=0.
I'm not sure, but I think the inexact +0.0 and -0.0 is counted as
'zero?', which might not be what you want it to do here. Being an
inexact input (representing a number near 0 but not necessarily exactly
0), and since 'atan2' is not locally constant at 0, the output would
need to be inexact too. Or, maybe you could let it return something
exact anyways, idk. Exactness/inexactness considerations can become a
bit arbitrary sometimes - sometimes '+0.0' is _exactly_ positive zero).
If you consider signed infinity to simply be the exact signed infinity,
you could also make (atan2 some-signed-infinity x) and (atan2 y
some-signed-infinity) exact. (If it instead is considered inexact, as in
maybe exact signed infinity, maybe a very large value, then this doesn't
follow).
In the new tests, it appears that you are only testing whether the
values (approximately) match, and not whether return values are exact
where they can be. Perhaps you could modify 'within-margin?' to do an
exactness check when the reference value is exact?
For the tangent, tan(45°) is rational despite sin(45°) and cos(45°)
being irrational. So, 'tangent' needs to be adjusted. Also, you should
consider what to do with (tangent 45) - return +infinity or raise an
exception for divide-by-zero? Either way, it's something to document.
For another test, you could check that (map (arcsine sine)
list-of-angles) equals list-of-angles (with exact comparison whenever
any of the compared things is exact, and approximate if both are
inexact). Likewise for (map (sine arcsine) list-of-ratios). This can
then easily be repeated for cosine and tangent (*).
(*) If 45° is included in the angles: assuming (tangent 90) returns
+infinity and (arctan +infinity) returns the exact 90. In case of
divide-by-zero exception, or (arctan +infinity) being inexact 90.0, this
wouldn't work as-is.
>+ (< (sqrt (expt (- value estimate) 2)) margin))
That's simply (< (abs (- value estimate)) margin), no? Or does Guile not
have 'abs'?
Best regards,
Maxime Devos