@@ -2,9 +2,13 @@ module Data.EuclideanRing
2
2
( class EuclideanRing , degree , div , mod , (/)
3
3
, gcd
4
4
, lcm
5
+ , quot
6
+ , rem
5
7
, module Data.CommutativeRing
6
8
, module Data.Ring
7
9
, module Data.Semiring
10
+ , intDiv
11
+ , intMod
8
12
) where
9
13
10
14
import Data.BooleanAlgebra ((||))
@@ -41,6 +45,25 @@ import Data.Semiring (class Semiring, add, mul, one, zero, (*), (+))
41
45
-- | for `degree` is simply `const 1`. In fact, unless there's a specific
42
46
-- | reason not to, `Field` types should normally use this definition of
43
47
-- | `degree`.
48
+ -- |
49
+ -- | The `EuclideanRing Int` instance is one of the most commonly used
50
+ -- | `EuclideanRing` instances and deserves a little more discussion. In
51
+ -- | particular, there are a few different sensible law-abiding implementations
52
+ -- | to choose from, with slightly different behaviour in the presence of
53
+ -- | negative dividends or divisors. The most common definitions are "truncating"
54
+ -- | division, where the result of `a / b` is rounded towards 0, and "Knuthian"
55
+ -- | or "flooring" division, where the result of `a / b` is rounded towards
56
+ -- | negative infinity. A slightly less common, but arguably more useful, option
57
+ -- | is "Euclidean" division, which is defined so as to ensure that ``a `mod` b``
58
+ -- | is always nonnegative. With Euclidean division, `a / b` rounds towards
59
+ -- | negative infinity if the divisor is positive, and towards positive infinity
60
+ -- | if the divisor is negative. Note that all three definitions are identical if
61
+ -- | we restrict our attention to nonnegative dividends and divisors.
62
+
63
+ -- | In versions 1.x, 2.x, and 3.x of the Prelude, the `EuclideanRing Int`
64
+ -- | instance used truncating division. As of 4.x, the `EuclideanRing Int`
65
+ -- | instance uses Euclidean division. Additional functions `quot` and `rem` are
66
+ -- | supplied if truncating division is desired.
44
67
class CommutativeRing a <= EuclideanRing a where
45
68
degree :: a -> Int
46
69
div :: a -> a -> a
@@ -77,3 +100,38 @@ lcm a b =
77
100
if a == zero || b == zero
78
101
then zero
79
102
else a * b / gcd a b
103
+
104
+ -- | The `quot` function provides _truncating_ integer division (see the
105
+ -- | documentation for the `EuclideanRing` class). It is identical to `div` in
106
+ -- | the `EuclideanRing Int` instance if the dividend is positive, but will be
107
+ -- | slightly different if the dividend is negative. For example:
108
+ -- |
109
+ -- | ```purescript
110
+ -- | div 2 3 == 0
111
+ -- | quot 2 3 == 0
112
+ -- |
113
+ -- | div (-2) 3 == (-1)
114
+ -- | quot (-2) 3 == 0
115
+ -- |
116
+ -- | div 2 (-3) == 0
117
+ -- | quot 2 (-3) == 0
118
+ -- | ```
119
+ foreign import quot :: Int -> Int -> Int
120
+
121
+ -- | The `rem` function provides the remainder after _truncating_ integer
122
+ -- | division (see the documentation for the `EuclideanRing` class). It is
123
+ -- | identical to `mod` in the `EuclideanRing Int` instance if the dividend is
124
+ -- | positive, but will be slightly different if the dividend is negative. For
125
+ -- | example:
126
+ -- |
127
+ -- | ```purescript
128
+ -- | mod 2 3 == 2
129
+ -- | rem 2 3 == 2
130
+ -- |
131
+ -- | mod (-2) 3 == 1
132
+ -- | rem (-2) 3 == (-2)
133
+ -- |
134
+ -- | mod 2 (-3) == 2
135
+ -- | rem 2 (-3) == 2
136
+ -- | ```
137
+ foreign import rem :: Int -> Int -> Int
0 commit comments