r10955: add upstream license file
[kmrcl.git] / math.lisp
index e9118443fdec24c716cf21898b42615ce5973692..c03b27f5d54238e5cfc1a48df0e43d7e3d3d5f8c 100644 (file)
--- a/math.lisp
+++ b/math.lisp
 
 (defun fixnum-width ()
   (nth-value 0 (truncate (+ (/ (log (1+ most-positive-fixnum)) (log 2)) .5))))
+
+(defun scaled-epsilon (float &optional (operation '+))
+  "Return the smallest number that would return a value different from
+  FLOAT if OPERATION were applied to FLOAT and this number.  OPERATION
+  should be either + or -, and defauls to +."
+  (multiple-value-bind (significand exponent)
+      (decode-float float)
+    (multiple-value-bind (1.0-significand 1.0-exponent)
+       (decode-float (float 1.0 float))
+      (if (and (eq operation '-)
+              (= significand 1.0-significand))
+         (scale-float (typecase float
+                        (short-float short-float-negative-epsilon)
+                        (single-float single-float-negative-epsilon)
+                        (double-float double-float-negative-epsilon)
+                        (long-float long-float-negative-epsilon))
+                      (- exponent 1.0-exponent))
+       (scale-float (typecase float
+                      (short-float short-float-epsilon)
+                      (single-float single-float-epsilon)
+                      (double-float double-float-epsilon)
+                      (long-float long-float-epsilon))
+                    (- exponent 1.0-exponent))))))
+
+(defun sinc (x)
+  (if (zerop x)
+      1d0
+    (let ((x (coerce x 'double-float)))
+      (/ (sin x) x))))
+
+
+(defun numbers-within-percentage (a b percent)
+  "Determines if two numbers are equal within a percentage difference."
+  (let ((abs-diff (* 0.01 percent 0.5 (+ (abs a) (abs b)))))
+    (< (abs (- a b)) abs-diff)))