Update of /project/oct/cvsroot/oct
In directory clnet:/tmp/cvs-serv1830
Added Files:
rt-tests.lisp
Log Message:
Tests using the RT framework.
--- /project/oct/cvsroot/oct/rt-tests.lisp 2007/08/27 18:05:12 NONE
+++ /project/oct/cvsroot/oct/rt-tests.lisp 2007/08/27 18:05:12 1.1
;;;; -*- Mode: lisp -*-
;;;;
;;;; Copyright (c) 2007 Raymond Toy
;;;;
;;;; Permission is hereby granted, free of charge, to any person
;;;; obtaining a copy of this software and associated documentation
;;;; files (the "Software"), to deal in the Software without
;;;; restriction, including without limitation the rights to use,
;;;; copy, modify, merge, publish, distribute, sublicense, and/or sell
;;;; copies of the Software, and to permit persons to whom the
;;;; Software is furnished to do so, subject to the following
;;;; conditions:
;;;;
;;;; The above copyright notice and this permission notice shall be
;;;; included in all copies or substantial portions of the Software.
;;;;
;;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
;;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
;;;; OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
;;;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
;;;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
;;;; WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
;;;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
;;;; OTHER DEALINGS IN THE SOFTWARE.
(in-package #:qd)
;; Compute how many bits are the same for two numbers EST and TRUE.
;; Return T if they are identical.
(defun bit-accuracy (est true)
(let* ((diff (abs (- est true)))
(err (float (if (zerop true)
diff
(/ diff (abs true)))
1d0)))
(if (zerop diff)
t
(- (log err 2)))))
(defun check-accuracy (limit est true)
(let ((bits (bit-accuracy est true)))
(if (numberp bits)
(if (< bits limit)
(list bits limit est true)))))
(defvar *null* (make-broadcast-stream))
;;; Some simple tests from the Yozo Hida's qd package.
;; Pi via Machin's formula
(rt:deftest oct.pi.machin
(let* ((*standard-output* *null*)
(val (make-instance 'qd-real :value (qdi::test2)))
(true qd:+pi+))
(check-accuracy 213 val true))
nil)
;; Pi via Salamin-Brent algorithm
(rt:deftest oct.pi.salamin-brent
(let* ((*standard-output* *null*)
(val (make-instance 'qd-real :value (qdi::test3)))
(true qd:+pi+))
(check-accuracy 202 val true))
nil)
;; Pi via Borweign's Quartic formula
(rt:deftest oct.pi.borweign
(let* ((*standard-output* *null*)
(val (make-instance 'qd-real :value (qdi::test4)))
(true qd:+pi+))
(check-accuracy 211 val true))
nil)
;; e via Taylor series
(rt:deftest oct.e.taylor
(let* ((*standard-output* *null*)
(val (make-instance 'qd-real :value (qdi::test5)))
(true (make-instance 'qd-real :value qdi::+qd-e+)))
(check-accuracy 212 val true))
nil)
;; log(2) via Taylor series
(rt:deftest oct.log2.taylor
(let* ((*standard-output* *null*)
(val (make-instance 'qd-real :value (qdi::test6)))
(true (make-instance 'qd-real :value qdi::+qd-log2+)))
(check-accuracy 212 val true))
nil)
;;; Tests of atan where we know the analytical result
(rt:deftest oct.atan.1
(let* ((arg (/ (sqrt #q3)))
(y (/ (atan arg) +pi+))
(true (/ #q6)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan.2
(let* ((arg (sqrt #q3))
(y (/ (atan arg) +pi+))
(true (/ #q3)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan.3
(let* ((arg #q1)
(y (/ (atan arg) +pi+))
(true (/ #q4)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan.4
(let* ((arg #q1q100)
(y (/ (atan arg) +pi+))
(true #q.5))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan.5
(let* ((arg #q-1q100)
(y (/ (atan arg) +pi+))
(true #q-.5))
(check-accuracy 212 y true))
nil)
(defun atan-qd/duplication (arg)
(make-instance 'qd-real
:value (qdi::atan-qd/duplication (qd-value arg))))
;;; Tests of atan where we know the analytical result. Same tests,
;;; but using the atan duplication formula.
(rt:deftest oct.atan/dup.1
(let* ((arg (/ (sqrt #q3)))
(y (/ (atan-qd/duplication arg) +pi+))
(true (/ #q6)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan/dup.2
(let* ((arg (sqrt #q3))
(y (/ (atan-qd/duplication arg) +pi+))
(true (/ #q3)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan/dup.3
(let* ((arg #q1)
(y (/ (atan-qd/duplication arg) +pi+))
(true (/ #q4)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan/dup.4
(let* ((arg #q1q100)
(y (/ (atan-qd/duplication arg) +pi+))
(true #q.5))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan/dup.5
(let* ((arg #q-1q100)
(y (/ (atan-qd/duplication arg) +pi+))
(true #q-.5))
(check-accuracy 212 y true))
nil)
;;; Tests of atan where we know the analytical result. Same tests,
;;; but using a CORDIC implementation.
(defun atan-qd/cordic (arg)
(make-instance 'qd-real
:value (qdi::atan-qd/cordic (qd-value arg))))
(rt:deftest oct.atan/cordic.1
(let* ((arg (/ (sqrt #q3)))
(y (/ (atan-qd/cordic arg) +pi+))
(true (/ #q6)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan/cordic.2
(let* ((arg (sqrt #q3))
(y (/ (atan-qd/cordic arg) +pi+))
(true (/ #q3)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan/cordic.3
(let* ((arg #q1)
(y (/ (atan-qd/cordic arg) +pi+))
(true (/ #q4)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan/cordic.4
(let* ((arg #q1q100)
(y (/ (atan-qd/cordic arg) +pi+))
(true #q.5))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.atan/cordic.5
(let* ((arg #q-1q100)
(y (/ (atan-qd/cordic arg) +pi+))
(true #q-.5))
(check-accuracy 212 y true))
nil)
;;; Tests of sin where we know the analytical result.
(rt:deftest oct.sin.1
(let* ((arg (/ +pi+ 6))
(y (sin arg))
(true #q.5))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.sin.2
(let* ((arg (/ +pi+ 4))
(y (sin arg))
(true (sqrt #q.5)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.sin.3
(let* ((arg (/ +pi+ 3))
(y (sin arg))
(true (/ (sqrt #q3) 2)))
(check-accuracy 212 y true))
nil)
;;; Tests of tan where we know the analytical result.
(rt:deftest oct.tan.1
(let* ((arg (/ +pi+ 6))
(y (tan arg))
(true (/ (sqrt #q3))))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.tan.2
(let* ((arg (/ +pi+ 4))
(y (tan arg))
(true #q1))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.tan.3
(let* ((arg (/ +pi+ 3))
(y (tan arg))
(true (sqrt #q3)))
(check-accuracy 212 y true))
nil)
;;; Tests of tan where we know the analytical result. Uses CORDIC
;;; algorithm.
(defun tan/cordic (arg)
(make-instance 'qd-real
:value (qdi::tan-qd/cordic (qd-value arg))))
(rt:deftest oct.tan/cordic.1
(let* ((arg (/ +pi+ 6))
(y (tan/cordic arg))
(true (/ (sqrt #q3))))
(check-accuracy 211 y true))
nil)
(rt:deftest oct.tan/cordic.2
(let* ((arg (/ +pi+ 4))
(y (tan/cordic arg))
(true #q1))
(check-accuracy 211 y true))
nil)
(rt:deftest oct.tan/cordic.3
(let* ((arg (/ +pi+ 3))
(y (tan/cordic arg))
(true (sqrt #q3)))
(check-accuracy 210 y true))
nil)
;;; Tests of asin where we know the analytical result.
(rt:deftest oct.asin.1
(let* ((arg #q.5)
(y (asin arg))
(true (/ +pi+ 6)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.asin.2
(let* ((arg (sqrt #q.5))
(y (asin arg))
(true (/ +pi+ 4)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.asin.3
(let* ((arg (/ (sqrt #q3) 2))
(y (asin arg))
(true (/ +pi+ 3)))
(check-accuracy 212 y true))
nil)
;;; Tests of log.
(rt:deftest oct.log.1
(let* ((arg #q2)
(y (log arg))
(true (make-instance 'qd-real :value qdi::+qd-log2+)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.log.2
(let* ((arg #q10)
(y (log arg))
(true (make-instance 'qd-real :value qdi::+qd-log10+)))
(check-accuracy 207 y true))
nil)
(rt:deftest oct.log.3
(let* ((arg (+ 1 (scale-float #q1 -80)))
(y (log arg))
(true #q8.2718061255302767487140834995607996176476940491239977084112840149578911975528492q-25))
(check-accuracy 212 y true))
nil)
;;; Tests of log using Newton iteration.
(defun log/newton (arg)
(make-instance 'qd-real
:value (qdi::log-qd/newton (qd-value arg))))
(rt:deftest oct.log/newton.1
(let* ((arg #q2)
(y (log/newton arg))
(true (make-instance 'qd-real :value qdi::+qd-log2+)))
(check-accuracy 212 y true))
nil)
(rt:deftest oct.log/newton.2
(let* ((arg #q10)
(y (log/newton arg))
(true (make-instance 'qd-real :value qdi::+qd-log10+)))
(check-accuracy 207 y true))
nil)
(rt:deftest oct.log/newton.3
(let* ((arg (+ 1 (scale-float #q1 -80)))
(y (log/newton arg))
(true #q8.2718061255302767487140834995607996176476940491239977084112840149578911975528492q-25))
(check-accuracy 212 y true))
nil)
;;; Tests of log using AGM.
(defun log/agm (arg)
(make-instance 'qd-real
:value (qdi::log-qd/agm (qd-value arg))))
(rt:deftest oct.log/agm.1
(let* ((arg #q2)
(y (log/agm arg))
(true (make-instance 'qd-real :value qdi::+qd-log2+)))
(check-accuracy 203 y true))
nil)
(rt:deftest oct.log/agm.2
(let* ((arg #q10)
(y (log/agm arg))
(true (make-instance 'qd-real :value qdi::+qd-log10+)))
(check-accuracy 205 y true))
nil)
(rt:deftest oct.log/agm.3
(let* ((arg (+ 1 (scale-float #q1 -80)))
(y (log/agm arg))
(true #q8.2718061255302767487140834995607996176476940491239977084112840149578911975528492q-25))
(check-accuracy 123 y true))
nil)
;;; Tests of log using AGM2, a faster variaton of AGM.
(defun log/agm2 (arg)
(make-instance 'qd-real
:value (qdi::log-qd/agm2 (qd-value arg))))
(rt:deftest oct.log/agm2.1
(let* ((arg #q2)
(y (log/agm2 arg))
(true (make-instance 'qd-real :value qdi::+qd-log2+)))
(check-accuracy 203 y true))
nil)
(rt:deftest oct.log/agm2.2
(let* ((arg #q10)
(y (log/agm2 arg))
(true (make-instance 'qd-real :value qdi::+qd-log10+)))
(check-accuracy 205 y true))
nil)
[147 lines skipped]