+;;; Commentary:
+;;
+;; @cindex normalise angle
+;; @cindex sine
+;; @cindex cosine
+;; @cindex angle, normalised
+;; @cindex angle, sine of
+;; @cindex angle, cosine of

Some others you can add:

* tangent
* arcsine
* arccosine
* arctan

Those can be quite convenient as well.

+;; This module defines functions for computing the sine and cosine of an angle,
+;; as more robust versions of the built-in sin and cos functions in Guile.
The built-in are robust too, as far as I know.
+;; They return exact values for angles representing up, down, left and right,
+;; regardless of whether they're negative or how many rotations occurred.

May be good to mention that is is in degrees instead of radians.

Also, why limit this to pi/2 increments?

Let 'f: R->R' be some trigonometric function (in degrees). Then, let S={x | x is rational and f(x) is rational}. What would be nice, is that f(x) would be exact whenever x is in S.

Looking at <https://math.stackexchange.com/questions/87756/when-is-sinx-rational>, it appears that for the sine, S is exactly the multiples of pi. (Ditto for cosine.)

I'm going to look into what's the case for 'tan'. For 'tan', tan(pi/4)=tan(45°) is rational as well - I'm going to look into whether the 'S' of 'tan' is only the integer multiples pi/4, or whether there are more.

I was wondering for a moment why the conversion to degrees instead of radians, but multiples of pi aren't exact, so that's all ok.

+;;; Code:
+
+(define-module (math trigonometry)
+  #:use-module (scheme documentation)
+  #:export (normalise-angle
+            sine
+            cosine))
+
+(define (normalise-angle angle)
+  "Return a normalised angle where 0 <= angle < 360."
+  (define angle-from-north (remainder angle 360))
+  (+ angle-from-north
+     (if (< angle-from-north 0) 360 0)))

You can avoid this 'if' by using 'floor-remainder' instead of 'remainder'.

You are assuming 'angle' is real. In this setting that seems quite reasonable, but it needs to be mentioned (sin can be, and is, extended to the complex plane).

+
+(define (sine angle)
+  "Calculate the sine of an angle,
+with full precision for 90 degree increments."
+  (define normalised-angle (normalise-angle angle))
+  (cond ((or (= normalised-angle 0) (= normalised-angle 180)) 0)
+       ((= normalised-angle 90) 1)
+       ((= normalised-angle 270) -1)
+       (else (sin normalised-angle))))

Err, please test 'sine' for some other angles, so that 'sin' is used for things not integer multiples of 90 (with some error margin to deal with inexactness). I'm pretty sure it's in radians.

(Usually I'd mention something about documentation here, but IIRC Guile-Lib has some set-up where it copies docstrings.)

Best regards, Maxime Devos

Reply via email to