{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {- Copyright (C) 2011 Dr. Alistair Ward This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -} {- | [@AUTHOR@] Dr. Alistair Ward [@DESCRIPTION@] Implements 'Test.QuickCheck.Arbitrary' and defines /QuickCheck/-properties for "Math.Implementations.SquareRoot". -} module Factory.Test.QuickCheck.SquareRoot( -- * Types -- ** Type-synonyms -- Testable, -- * Functions quickChecks ) where import Control.Applicative((<$>)) import Data.Ratio((%)) import qualified Data.Ratio import qualified Factory.Math.Implementations.SquareRoot as Math.Implementations.SquareRoot import qualified Factory.Math.Power as Math.Power import qualified Factory.Math.Precision as Math.Precision import qualified Factory.Math.SquareRoot as Math.SquareRoot import qualified Test.QuickCheck instance Test.QuickCheck.Arbitrary (Math.Implementations.SquareRoot.Algorithm) where arbitrary = Test.QuickCheck.oneof [ Test.QuickCheck.elements [ Math.Implementations.SquareRoot.BakhshaliApproximation, Math.Implementations.SquareRoot.ContinuedFraction, Math.Implementations.SquareRoot.HalleysMethod, Math.Implementations.SquareRoot.NewtonRaphsonIteration ], Math.Implementations.SquareRoot.TaylorSeries <$> Test.QuickCheck.elements [2 .. 32] ] #if !(MIN_VERSION_QuickCheck(2,1,0)) coarbitrary = undefined --CAVEAT: stops warnings from ghc. #endif type Testable = (Math.Implementations.SquareRoot.Algorithm, Math.Precision.DecimalDigits, Data.Ratio.Rational) -> Test.QuickCheck.Property -- | Defines invariant properties. quickChecks :: IO () quickChecks = Test.QuickCheck.quickCheck `mapM_` [prop_accuracy, prop_factorable, prop_perfectSquare] where prop_accuracy, prop_factorable, prop_perfectSquare :: Testable prop_accuracy (algorithm, decimalDigits, operand) = Test.QuickCheck.label "prop_accuracy" . (>= requiredDecimalDigits) . Math.SquareRoot.getAccuracy operand' $ Math.SquareRoot.squareRoot algorithm requiredDecimalDigits operand' where requiredDecimalDigits :: Math.Precision.DecimalDigits requiredDecimalDigits = 1 + (decimalDigits `mod` 1024) operand' :: Data.Ratio.Rational operand' = abs operand prop_factorable (algorithm, decimalDigits, operand) = Test.QuickCheck.label "prop_factorable" . (<= 5) . ( * 10 ^ requiredDecimalDigits --Promote the relative error. ) . abs $ 1 - ( Math.SquareRoot.squareRoot algorithm requiredDecimalDigits ( toRational $ Data.Ratio.numerator operand' ) / Math.SquareRoot.squareRoot algorithm requiredDecimalDigits ( toRational $ Data.Ratio.denominator operand' ) ) / Math.SquareRoot.squareRoot algorithm requiredDecimalDigits operand' where requiredDecimalDigits :: Math.Precision.DecimalDigits requiredDecimalDigits = 1 + (decimalDigits `mod` 1024) operand' :: Data.Ratio.Rational operand' = 1 + abs operand prop_perfectSquare (algorithm, decimalDigits, operand) = Test.QuickCheck.label "prop_perfectSquare" . Math.SquareRoot.isPrecise perfectSquare $ Math.SquareRoot.squareRoot algorithm requiredDecimalDigits perfectSquare where requiredDecimalDigits :: Math.Precision.DecimalDigits requiredDecimalDigits = 1 + (decimalDigits `mod` 32768) operand', perfectSquare :: Data.Ratio.Rational operand' = (abs (Data.Ratio.numerator operand) `min` (2 ^ (32 :: Int))) % (abs (Data.Ratio.denominator operand) `min` (2 ^ (32 :: Int))) --Avoid floating-point rounding-errors in 'Math.SquareRoot.rSqrt'. perfectSquare = Math.Power.square operand'