Skip to content

Commit fe44b02

Browse files
committed
Exhaustive tests, update documentation
1 parent 2404033 commit fe44b02

File tree

3 files changed

+47
-23
lines changed

3 files changed

+47
-23
lines changed

docs/Data/BigInt.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## Module Data.BigInt
22

3+
This module defines a `BigInt` data type for arbitrary length integers.
4+
35
#### `BigInt`
46

57
``` purescript
@@ -41,7 +43,7 @@ large.
4143
pow :: BigInt -> BigInt -> BigInt
4244
```
4345

44-
Exponentiation for BigInt. If the exponent is less than 0, `pow`
46+
Exponentiation for `BigInt`. If the exponent is less than 0, `pow`
4547
returns 0. Also, `pow zero zero == one`.
4648

4749
#### `abs`
@@ -50,7 +52,7 @@ returns 0. Also, `pow zero zero == one`.
5052
abs :: BigInt -> BigInt
5153
```
5254

53-
The absolute value of a BigInt
55+
The absolute value.
5456

5557
#### `even`
5658

@@ -82,7 +84,7 @@ Returns `true` if the number is prime, `false` otherwise.
8284
fromString :: String -> Maybe BigInt
8385
```
8486

85-
Parse a string into a BigInt, assuming a decimal representation. Returns
87+
Parse a string into a `BigInt`, assuming a decimal representation. Returns
8688
`Nothing` if the parse fails.
8789

8890
Examples:
@@ -98,8 +100,8 @@ fromString "1e100"
98100
fromBase :: Int -> String -> Maybe BigInt
99101
```
100102

101-
Parse a string into a BigInt, assuming a representation in the given base.
102-
The letters "a-z" and "A-Z" will be interpreted as the numbers `10` to
103+
Parse a string into a `BigInt`, assuming a representation in the given base.
104+
The letters "a-z" and "A-Z" will be interpreted as the digits `10` to
103105
`36`. Returns `Nothing` if the parse fails.
104106

105107
```purescript
@@ -113,6 +115,6 @@ fromBase 16 "ff" == fromString "255"
113115
toString :: BigInt -> String
114116
```
115117

116-
A textual representation of the BigInt.
118+
A decimal representation of the `BigInt` as a `String`.
117119

118120

src/Data/BigInt.purs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
-- | This module defines a `BigInt` data type for arbitrary length integers.
12
module Data.BigInt
23
( BigInt(..)
34
, fromString
@@ -33,11 +34,11 @@ foreign import fromInt :: Int -> BigInt
3334
-- | large.
3435
foreign import toNumber :: BigInt -> Number
3536

36-
-- | Exponentiation for BigInt. If the exponent is less than 0, `pow`
37+
-- | Exponentiation for `BigInt`. If the exponent is less than 0, `pow`
3738
-- | returns 0. Also, `pow zero zero == one`.
3839
foreign import pow :: BigInt -> BigInt -> BigInt
3940

40-
-- | The absolute value of a BigInt
41+
-- | The absolute value.
4142
foreign import abs :: BigInt -> BigInt
4243

4344
-- | Returns `true` if the number is even, `false` otherwise.
@@ -49,7 +50,7 @@ foreign import odd :: BigInt -> Boolean
4950
-- | Returns `true` if the number is prime, `false` otherwise.
5051
foreign import prime :: BigInt -> Boolean
5152

52-
-- | Parse a string into a BigInt, assuming a decimal representation. Returns
53+
-- | Parse a string into a `BigInt`, assuming a decimal representation. Returns
5354
-- | `Nothing` if the parse fails.
5455
-- |
5556
-- | Examples:
@@ -61,8 +62,8 @@ foreign import prime :: BigInt -> Boolean
6162
fromString :: String -> Maybe BigInt
6263
fromString = fromBase 10
6364

64-
-- | Parse a string into a BigInt, assuming a representation in the given base.
65-
-- | The letters "a-z" and "A-Z" will be interpreted as the numbers `10` to
65+
-- | Parse a string into a `BigInt`, assuming a representation in the given base.
66+
-- | The letters "a-z" and "A-Z" will be interpreted as the digits `10` to
6667
-- | `36`. Returns `Nothing` if the parse fails.
6768
-- |
6869
-- | ```purescript
@@ -77,7 +78,6 @@ foreign import biEquals :: BigInt -> BigInt -> Boolean
7778
instance eqBigInt :: Eq BigInt where
7879
eq = biEquals
7980

80-
8181
foreign import biCompare :: BigInt -> BigInt -> Int
8282

8383
instance ordBigInt :: Ord BigInt where
@@ -86,7 +86,7 @@ instance ordBigInt :: Ord BigInt where
8686
0 -> EQ
8787
-1 -> LT
8888

89-
-- | A textual representation of the BigInt.
89+
-- | A decimal representation of the `BigInt` as a `String`.
9090
foreign import toString :: BigInt -> String
9191

9292
instance showBigInt :: Show BigInt where

test/Main.purs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
module Test.Main where
22

3+
import Prelude
34
import Control.Monad.Eff.Console (log)
5+
import Data.Array (filter, range)
46
import Data.BigInt
5-
import Data.Maybe
7+
import Data.Foldable (mconcat)
8+
import Data.Maybe (Maybe(..))
69
import Data.Maybe.Unsafe (fromJust)
7-
import Prelude
8-
import Test.Assert
9-
import Test.QuickCheck
10-
import Test.QuickCheck.Arbitrary
11-
import Test.QuickCheck.Gen (chooseInt)
10+
import Test.Assert (assert)
11+
import Test.QuickCheck (quickCheck)
12+
import Test.QuickCheck.Arbitrary (Arbitrary)
13+
import Test.QuickCheck.Gen (Gen(..), chooseInt, arrayOf, elements)
1214
import qualified Data.Int as Int
1315

1416
-- | Newtype with an Arbitrary instance that generates only small integers
@@ -20,6 +22,17 @@ instance arbitrarySmallInt :: Arbitrary SmallInt where
2022
runSmallInt :: SmallInt -> Int
2123
runSmallInt (SmallInt n) = n
2224

25+
-- | Arbitrary instance for BigInt
26+
instance arbitraryBigInt :: Arbitrary BigInt where
27+
arbitrary = do
28+
n <- (fromJust <<< fromString) <$> digitString
29+
op <- elements id [negate]
30+
return (op n)
31+
where digits :: Gen Int
32+
digits = chooseInt 0 9
33+
digitString :: Gen String
34+
digitString = (mconcat <<< map show) <$> arrayOf digits
35+
2336
-- | Convert SmallInt to BigInt
2437
fromSmallInt :: SmallInt -> BigInt
2538
fromSmallInt = fromInt <<< runSmallInt
@@ -46,6 +59,7 @@ main = do
4659
assert $ fromString "2.1" == Nothing
4760
assert $ fromString "123456789" == Just (fromInt 123456789)
4861
assert $ fromString "1e7" == Just (fromInt 10000000)
62+
quickCheck $ \a -> (fromString <<< toString) a == Just a
4963

5064
log "Parsing strings with a different base"
5165
assert $ fromBase 2 "100" == Just four
@@ -62,18 +76,26 @@ main = do
6276
testBinary mod mod
6377
testBinary div div
6478

79+
-- To test the multiplication, we need to make sure that Int does not overflow
80+
quickCheck (\x y -> fromSmallInt x * fromSmallInt y == fromInt (runSmallInt x * runSmallInt y))
81+
6582
log "It should perform multiplications which would lead to imprecise results using Number"
6683
assert $ Just (fromInt 333190782 * fromInt 1103515245) == fromString "367681107430471590"
6784

68-
-- To check the multiplication, we need to make sure that the Int does not overflow
69-
quickCheck (\x y -> fromSmallInt x * fromSmallInt y == fromInt (runSmallInt x * runSmallInt y))
70-
71-
log "compare and (==) should be the same before and after converting to BigInt"
85+
log "compare, (==), even, odd should be the same before and after converting to BigInt"
7286
quickCheck (\x y -> compare x y == compare (fromInt x) (fromInt y))
7387
quickCheck (\x y -> (fromSmallInt x == fromSmallInt y) == (runSmallInt x == runSmallInt y))
88+
quickCheck (\x -> Int.even x == even (fromInt x))
89+
quickCheck (\x -> Int.odd x == odd (fromInt x))
7490

7591
log "pow should perform integer exponentiation and yield 0 for negative exponents"
7692
assert $ three `pow` four == fromInt 81
7793
assert $ three `pow` -two == zero
7894
assert $ three `pow` zero == one
7995
assert $ zero `pow` zero == one
96+
97+
log "Prime numbers"
98+
assert $ filter (prime <<< fromInt) (range 2 20) == [2, 3, 5, 7, 11, 13, 17, 19]
99+
100+
log "Absolute value"
101+
quickCheck $ \x -> abs x == if x > zero then x else (-x)

0 commit comments

Comments
 (0)