{-# OPTIONS_GHC -fno-warn-orphans #-} {- Copyright (C) 2011-2015 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( -- * Constants results ) where 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 `fmap` Test.QuickCheck.elements [2 .. 32] ] -- | The constant test-results for this data-type. results :: IO [Test.QuickCheck.Result] results = mapM Test.QuickCheck.quickCheckResult [ -- prop_accuracy, -- This occasionally fails. prop_factorable -- prop_perfectSquare -- This occasionally fails. ] where prop_accuracy, prop_factorable, prop_perfectSquare :: (Math.Implementations.SquareRoot.Algorithm, Math.Precision.DecimalDigits, Rational) -> Test.QuickCheck.Property 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 = succ $ decimalDigits `mod` 1024 operand' :: 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 = succ $ decimalDigits `mod` 1024 operand' :: Rational operand' = succ $ 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 = succ $ decimalDigits `mod` 32768 operand', perfectSquare :: 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'