arithmoi-0.9.0.0: test-suite/Math/NumberTheory/Powers/FourthTests.hs
-- |
-- Module: Math.NumberTheory.Powers.FourthTests
-- Copyright: (c) 2016 Andrew Lelechenko
-- Licence: MIT
-- Maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>
--
-- Tests for Math.NumberTheory.Powers.Fourth
--
{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
module Math.NumberTheory.Powers.FourthTests
( testSuite
) where
import Test.Tasty
import Test.Tasty.HUnit
import Data.Maybe
import Math.NumberTheory.Powers.Fourth
import Math.NumberTheory.TestUtils
#include "MachDeps.h"
-- | Check that 'integerFourthRoot' returns the largest integer @m@ with @m^4 <= n@.
--
-- (m + 1) ^ 4 /= n && (m + 1) ^ 3 >= n `div` (m + 1)
-- means
-- (m + 1) ^ 4 > n
-- but without overflow for bounded types
integerFourthRootProperty :: Integral a => NonNegative a -> Bool
integerFourthRootProperty (NonNegative n) = m >= 0 && m ^ 4 <= n && (m + 1) ^ 4 /= n && (m + 1) ^ 3 >= n `div` (m + 1)
where
m = integerFourthRoot n
-- | Specialized to trigger 'biSqrtInt'.
integerFourthRootProperty_Int :: NonNegative Int -> Bool
integerFourthRootProperty_Int = integerFourthRootProperty
-- | Specialized to trigger 'biSqrtWord'.
integerFourthRootProperty_Word :: NonNegative Word -> Bool
integerFourthRootProperty_Word = integerFourthRootProperty
-- | Specialized to trigger 'biSqrtIgr'.
integerFourthRootProperty_Integer :: NonNegative Integer -> Bool
integerFourthRootProperty_Integer = integerFourthRootProperty
-- | Check that 'integerFourthRoot' returns the largest integer @m@ with @m^4 <= n@, , where @n@ has form @k@^4-1.
integerFourthRootProperty2 :: Integral a => Positive a -> Bool
integerFourthRootProperty2 (Positive k) = n < 0 || m >= 0 && m ^ 4 <= n && (m + 1) ^ 4 /= n && (m + 1) ^ 3 >= n `div` (m + 1)
where
n = k ^ 4 - 1
m = integerFourthRoot n
-- | Specialized to trigger 'biSqrtInt.
integerFourthRootProperty2_Int :: Positive Int -> Bool
integerFourthRootProperty2_Int = integerFourthRootProperty2
-- | Specialized to trigger 'biSqrtWord'.
integerFourthRootProperty2_Word :: Positive Word -> Bool
integerFourthRootProperty2_Word = integerFourthRootProperty2
#if WORD_SIZE_IN_BITS == 64
-- | Check that 'integerFourthRoot' of 2^60-1 is 2^15-1, not 2^15.
integerFourthRootSpecialCase1_Int :: Assertion
integerFourthRootSpecialCase1_Int =
assertEqual "integerFourthRoot" (integerFourthRoot (maxBound `div` 8 :: Int)) (2 ^ 15 - 1)
-- | Check that 'integerFourthRoot' of 2^60-1 is 2^15-1, not 2^15.
integerFourthRootSpecialCase1_Word :: Assertion
integerFourthRootSpecialCase1_Word =
assertEqual "integerFourthRoot" (integerFourthRoot (maxBound `div` 16 :: Word)) (2 ^ 15 - 1)
-- | Check that 'integerFourthRoot' of 2^64-1 is 2^16-1, not 2^16.
integerFourthRootSpecialCase2 :: Assertion
integerFourthRootSpecialCase2 =
assertEqual "integerFourthRoot" (integerFourthRoot (maxBound :: Word)) (2 ^ 16 - 1)
#endif
-- | Check that 'integerFourthRoot'' returns the largest integer @m@ with @m^4 <= n@.
integerFourthRoot'Property :: Integral a => NonNegative a -> Bool
integerFourthRoot'Property (NonNegative n) = m >= 0 && m ^ 4 <= n && (m + 1) ^ 4 /= n && (m + 1) ^ 3 >= n `div` (m + 1)
where
m = integerFourthRoot' n
-- | Check that the number 'isFourthPower' iff its 'integerFourthRoot' is exact.
isFourthPowerProperty :: Integral a => AnySign a -> Bool
isFourthPowerProperty (AnySign n) = (n < 0 && not t) || (n /= m ^ 4 && not t) || (n == m ^ 4 && t)
where
t = isFourthPower n
m = integerFourthRoot n
-- | Check that the number 'isFourthPower'' iff its 'integerFourthRoot'' is exact.
isFourthPower'Property :: Integral a => NonNegative a -> Bool
isFourthPower'Property (NonNegative n) = (n /= m ^ 4 && not t) || (n == m ^ 4 && t)
where
t = isFourthPower' n
m = integerFourthRoot' n
-- | Check that 'exactFourthRoot' returns an exact integer root of fourth power
-- and is consistent with 'isFourthPower'.
exactFourthRootProperty :: Integral a => AnySign a -> Bool
exactFourthRootProperty (AnySign n) = case exactFourthRoot n of
Nothing -> not (isFourthPower n)
Just m -> isFourthPower n && n == m ^ 4
-- | Check that 'isPossibleFourthPower' is consistent with 'exactFourthRoot'.
isPossibleFourthPowerProperty :: Integral a => NonNegative a -> Bool
isPossibleFourthPowerProperty (NonNegative n) = t || not t && isNothing m
where
t = isPossibleFourthPower n
m = exactFourthRoot n
testSuite :: TestTree
testSuite = testGroup "Fourth"
[ testGroup "integerFourthRoot"
[ testIntegralProperty "generic" integerFourthRootProperty
, testSmallAndQuick "generic Int" integerFourthRootProperty_Int
, testSmallAndQuick "generic Word" integerFourthRootProperty_Word
, testSmallAndQuick "generic Integer" integerFourthRootProperty_Integer
, testIntegralProperty "almost Fourth" integerFourthRootProperty2
, testSmallAndQuick "almost Fourth Int" integerFourthRootProperty2_Int
, testSmallAndQuick "almost Fourth Word" integerFourthRootProperty2_Word
#if WORD_SIZE_IN_BITS == 64
, testCase "maxBound / 8 :: Int" integerFourthRootSpecialCase1_Int
, testCase "maxBound / 16 :: Word" integerFourthRootSpecialCase1_Word
, testCase "maxBound :: Word" integerFourthRootSpecialCase2
#endif
]
, testIntegralProperty "integerFourthRoot'" integerFourthRoot'Property
, testIntegralProperty "isFourthPower" isFourthPowerProperty
, testIntegralProperty "isFourthPower'" isFourthPower'Property
, testIntegralProperty "exactFourthRoot" exactFourthRootProperty
, testIntegralProperty "isPossibleFourthPower" isPossibleFourthPowerProperty
]