1 (* Copyright (C
) 1999-2006 Henry Cejtin
, Matthew Fluet
, Suresh
2 * Jagannathan
, and Stephen Weeks
.
3 * Copyright (C
) 1997-2000 NEC Research Institute
.
5 * MLton is released under a BSD
-style license
.
6 * See the file MLton
-LICENSE for details
.
9 functor Integer (I
: PRIM_INTEGER
): INTEGER_EXTRA
=
15 val precision
': Int.int = Primitive
.Int32
.zextdToInt sizeInBits
16 val precision
: Int.int option
= SOME precision
'
17 val sizeInBitsWord
= Primitive
.Word32
.zextdToWord sizeInBitsWord
19 val maxInt
: int option
= SOME maxInt
'
20 val minInt
: int option
= SOME minInt
'
22 val sign
: int -> Int.int =
29 fun sameSign (x
, y
) = sign x
= sign y
32 if Word.>= (n
, sizeInBitsWord
)
34 else I
.<<?
(i
, Primitive
.Word32
.zextdFromWord n
)
36 if Word.>= (n
, sizeInBitsWord
)
38 else I
.>>?
(i
, Primitive
.Word32
.zextdFromWord n
)
40 if Word.< (n
, sizeInBitsWord
)
41 then I
.~
>>?
(i
, Primitive
.Word32
.zextdFromWord n
)
42 else I
.~
>>?
(i
, Primitive
.Word32
.- (I
.sizeInBitsWord
, 0w1
))
43 fun rol (i
, n
) = I
.rolUnsafe (i
, Primitive
.Word32
.zextdFromWord n
)
44 fun ror (i
, n
) = I
.rorUnsafe (i
, Primitive
.Word32
.zextdFromWord n
)
46 val fromInt
= I
.schckFromInt
47 val toInt
= I
.schckToInt
49 val fromLargeInt
= I
.schckFromLargeInt
50 val toLargeInt
= I
.schckToLargeInt
51 val fromLarge
= fromLargeInt
52 val toLarge
= toLargeInt
54 (* fmt constructs a
string to represent the integer by building it into a
55 * statically allocated buffer
. For the most part
, this is a textbook
56 * algorithm
: loop starting at the
end of the buffer
; we use rem to
57 * extract the next digit to put into the buffer
; and we use quot to
58 * figure out the part
of the integer that we haven
't yet formatted
.
59 * However
, this function uses the negative absolute value
of the input
60 * number
, which allows it to take into account minInt without any
61 * special
-casing
. This requires the rem function to behave
in a very
62 * specific way
, or
else things will go terribly wrong
. This may be a
63 * concern when porting to platforms
where the division hardware has a
64 * different interpretation than SML about what happens when doing
65 * division
of negative numbers
.
68 (* Allocate a buffer large enough to hold any formatted integer
in any radix
.
69 * The most that will be required is for minInt
in binary
.
71 val maxNumDigits
= Int.+ (precision
', 1)
72 val oneBuf
= One
.make (fn () => CharArray
.array (maxNumDigits
, #
"\000"))
74 fun fmt
radix (n
: int): string =
78 val radix
= fromInt (StringCvt.radixToInt radix
)
79 fun loop (q
, i
: Int.int) =
83 (buf
, i
, StringCvt.digitToChar (toInt (~?
(rem (q
, radix
)))))
84 val q
= quot (q
, radix
)
94 val () = CharArray
.update (buf
, i
, #
"~")
100 CharArraySlice
.vector
101 (CharArraySlice
.slice (buf
, start
, NONE
))
103 else loop (q
, Int.- (i
, 1))
106 loop (if n
< zero
then n
else ~? n
, Int.- (maxNumDigits
, 1))
110 val toString
= fmt
StringCvt.DEC
112 fun scan radix reader s
=
114 (* Works
with the negative
of the number so that minInt can be scanned
. *)
115 val s
= StringCvt.skipWS reader s
117 case StringCvt.charToDigit radix c
of
119 | SOME n
=> SOME (fromInt n
)
120 val radixInt
= fromInt (StringCvt.radixToInt radix
)
121 fun finishNum (s
, n
) =
125 case charToDigit c
of
127 | SOME n
' => finishNum (s
', n
* radixInt
- n
')
129 case (reader s
, radix
) of
131 |
(SOME (#
"0", s
), StringCvt.HEX
) =>
133 NONE
=> SOME (zero
, s
)
135 if c
= #
"x" orelse c
= #
"X" then
137 NONE
=> SOME (zero
, s
)
139 case charToDigit c
of
140 NONE
=> SOME (zero
, s
)
141 | SOME n
=> finishNum (s
', ~? n
)
143 case charToDigit c
of
144 NONE
=> SOME (zero
, s
)
145 | SOME n
=> finishNum (s
', ~? n
))
146 |
(SOME (c
, s
), _
) =>
147 case charToDigit c
of
149 | SOME n
=> finishNum (s
, ~? n
)
153 |
SOME (n
, s
) => SOME (~ n
, s
)
165 val fromString
= StringCvt.scanString (scan
StringCvt.DEC
)
169 structure Int8
= Integer (Primitive
.Int8
)
170 structure Int16
= Integer (Primitive
.Int16
)
171 structure Int32
= Integer (Primitive
.Int32
)
172 structure Int64
= Integer (Primitive
.Int64
)