Import Upstream version 20180207
[hcoop/debian/mlton.git] / regression / smith-normal-form.sml
CommitLineData
7f918cf1
CE
1signature MATRIX =
2 sig
3 type 'entry matrix
4 val make: int * int * (int * int -> 'entry) -> 'entry matrix
5 val height: 'entry matrix -> int
6 val width: 'entry matrix -> int
7 val fetch: 'entry matrix * int * int -> 'entry
8 val fetchRow: 'entry matrix * int -> int -> 'entry
9 val fetchCol: 'entry matrix * int -> int -> 'entry
10 val store: 'entry matrix * int * int * 'entry -> unit
11 val storeRow: 'entry matrix * int -> int * 'entry -> unit
12 val storeCol: 'entry matrix * int -> int * 'entry -> unit
13 val rowSwap: 'entry matrix * int * int -> unit
14 val colSwap: 'entry matrix * int * int -> unit
15 val rowOp: 'entry matrix * int * int * ('entry * 'entry -> 'entry) -> unit
16 val colOp: 'entry matrix * int * int * ('entry * 'entry -> 'entry) -> unit
17 val copy: 'entry matrix -> 'entry matrix
18 val map: 'entry1 matrix * ('entry1 -> 'entry2) -> 'entry2 matrix
19 val toString: 'entry matrix * ('entry -> string) -> string
20 end
21
22structure Matrix:> MATRIX =
23 struct
24 type 'entry matrix = int * int * 'entry array
25
26 exception sizeError
27
28 exception index
29
30 exception foldError
31
32 fun make (height: int, width: int, generator: int * int -> 'entry)
33 : 'entry matrix =
34 if height < 0 orelse width < 0
35 then raise sizeError
36 else (height,
37 width,
38 Array.tabulate (height*width,
39 fn z => generator (z div width,
40 z mod width)))
41
42 fun height (height, _, _) = height
43
44 fun width (width, _, _) = width
45
46 fun fetch ((height, width, mat), row, col) =
47 if 0 <= row
48 andalso row < height
49 andalso 0 <= col
50 andalso col < width
51 then Array.sub (mat, col + width*row)
52 else raise index
53
54 fun fetchRow ((height, width, mat), row) =
55 if 0 <= row andalso row < height
56 then let val offset = width * row
57 in fn col =>
58 if 0 <= col andalso col < width
59 then Array.sub (mat, col + offset)
60 else raise index
61 end
62 else raise index
63
64 fun fetchCol ((height, width, mat), col) =
65 if 0 <= col andalso col < width
66 then fn row =>
67 if 0 <= row andalso row < height
68 then Array.sub (mat, col + width*row)
69 else raise index
70 else raise index
71
72 fun store ((height, width, mat), row, col, entry) =
73 if 0 <= row
74 andalso row < height
75 andalso 0 <= col
76 andalso col < width
77 then Array.update (mat, col + width*row, entry)
78 else raise index
79
80 fun storeRow ((height, width, mat), row) =
81 if 0 <= row andalso row < height
82 then let val offset = width * row
83 in fn (col, entry) =>
84 if 0 <= col andalso col < width
85 then Array.update (mat, col + offset, entry)
86 else raise index
87 end
88 else raise index
89
90 fun storeCol ((height, width, mat), col) =
91 if 0 <= col andalso col < width
92 then fn (row, entry) =>
93 if 0 <= row andalso row < height
94 then Array.update (mat, col + width*row, entry)
95 else raise index
96 else raise index
97
98 fun swapLoop (from1: int -> 'entry,
99 to1: int * 'entry -> unit,
100 from2: int -> 'entry,
101 to2: int * 'entry -> unit,
102 limit: int): unit =
103 let fun loop (i: int): unit =
104 if i = limit
105 then ()
106 else let val tmp = from1 i
107 in to1 (i, from2 i);
108 to2 (i, tmp);
109 loop (i + 1)
110 end
111 in loop 0
112 end
113
114 fun rowSwap (mat as (height, width, _), row1, row2): unit =
115 if 0 <= row1 andalso row1 < height
116 andalso 0 <= row2 andalso row2 < height
117 then if row1 = row2
118 then ()
119 else swapLoop (fetchRow (mat, row1),
120 storeRow (mat, row1),
121 fetchRow (mat, row2),
122 storeRow (mat, row2),
123 width)
124 else raise index
125
126 fun colSwap (mat as (height, width, _), col1, col2): unit =
127 if 0 <= col1 andalso col1 < width
128 andalso 0 <= col2 andalso col2 < width
129 then if col1 = col2
130 then ()
131 else swapLoop (fetchCol (mat, col1),
132 storeCol (mat, col1),
133 fetchCol (mat, col2),
134 storeCol (mat, col2),
135 height)
136 else raise index
137
138 fun opLoop (from1: int -> 'entry,
139 from2: int -> 'entry,
140 to2: int * 'entry -> unit,
141 limit: int,
142 f: 'entry * 'entry -> 'entry): unit =
143 let fun loop (i: int): unit =
144 if i = limit
145 then ()
146 else (
147 to2 (i,
148 f (from1 i, from2 i));
149 loop (i + 1))
150 in loop 0
151 end
152
153 fun rowOp (mat as (height, width, _),
154 row1,
155 row2,
156 f: 'entry * 'entry -> 'entry): unit =
157 if 0 <= row1 andalso row1 < height
158 andalso 0 <= row2 andalso row2 < height
159 andalso row1 <> row2
160 then opLoop (fetchRow (mat, row1),
161 fetchRow (mat, row2),
162 storeRow (mat, row2),
163 width,
164 f)
165 else raise index
166
167 fun colOp (mat as (height, width, _),
168 col1,
169 col2,
170 f: 'entry * 'entry -> 'entry): unit =
171 if 0 <= col1 andalso col1 < width
172 andalso 0 <= col2 andalso col2 < width
173 andalso col1 <> col2
174 then opLoop (fetchCol (mat, col1),
175 fetchCol (mat, col2),
176 storeCol (mat, col2),
177 height,
178 f)
179 else raise index
180
181 fun copy ((height, width, mat)) =
182 (height,
183 width,
184 Array.tabulate (Array.length mat,
185 fn i => Array.sub (mat, i)))
186
187 fun map ((height, width, mat: 'entry1 Array.array),
188 f: 'entry1 -> 'entry2)
189 : 'entry2 matrix =
190 (height,
191 width,
192 Array.tabulate (Array.length mat,
193 fn i => f (Array.sub (mat, i))))
194
195 (* Natural fold a range of integers in reverse. *)
196 fun naturalFold (limit: int,
197 state: 'state,
198 folder: int * 'state -> 'state): 'state =
199 let fun loop (i: int, state: 'state) =
200 if i = 0
201 then state
202 else loop (i - 1, folder (i - 1, state))
203 in if limit < 0
204 then raise foldError
205 else loop (limit, state)
206 end
207
208
209 local val blank8 = Byte.charToByte #" "
210
211 fun makeBlanks size =
212 let val blanks = Word8Vector.tabulate (size,
213 fn _ => blank8)
214 in Byte.bytesToString blanks
215 end
216
217 in fun toString (mat: 'entry matrix, f: 'entry -> string): string =
218 let val mat as (height, width, _) = map (mat, f)
219 fun maxSize from (i, width) = Int.max (String.size (from i),
220 width)
221 fun colWidth col = naturalFold (height,
222 0,
223 maxSize (fetchCol (mat,
224 col)))
225 val widths = Vector.tabulate (width, colWidth)
226 fun doRow (row: int, ac: string list): string list =
227 let val from = fetchRow (mat, row)
228 fun loop (col: int, ac: string list) =
229 let val next = from col
230 val ac = next::ac
231 val s = String.size next
232 val pad = Vector.sub (widths, col) - s
233 val ac = if pad <= 0
234 then ac
235 else (makeBlanks pad)::ac
236 in if col = 0
237 then ac
238 else loop (col - 1,
239 " "::ac)
240 end
241 val ac = "\n"::ac
242 in if width = 0
243 then ac
244 else loop (width - 1, ac)
245 end
246 val pieces = naturalFold (height,
247 [],
248 doRow)
249 in String.concat pieces
250 end
251 end
252 end
253
254val zero = IntInf.fromInt 0
255
256fun smaller (a: IntInf.int, b: IntInf.int): bool =
257 (not (a = zero))
258 andalso (b = zero orelse IntInf.< (IntInf.abs a , IntInf.abs b))
259
260fun smithNormalForm (mat: IntInf.int Matrix.matrix): IntInf.int Matrix.matrix =
261 let val height = Matrix.height mat
262 val width = Matrix.width mat
263 val mat = Matrix.copy mat
264 val range = Int.min (width, height)
265 fun dd pos =
266 let val matCol = Matrix.fetchCol (mat, pos)
267 val matRow = Matrix.fetchRow (mat, pos)
268 val _ = print ("dd: pos = " ^ (Int.toString pos) ^ "\n")
269 fun swapRowLoop (best, bestRow, bestCol, row) =
270 if row >= height
271 then (Matrix.rowSwap (mat, pos, bestRow);
272 Matrix.colSwap (mat, pos, bestCol))
273 else let val matRow = Matrix.fetchRow (mat, row)
274 fun swapColLoop (best, bestRow, bestCol, col) =
275 if col >= width
276 then swapRowLoop (best, bestRow, bestCol, row + 1)
277 else let val next = matRow col
278 in if smaller (next, best)
279 then swapColLoop (next, row, col, col + 1)
280 else swapColLoop (best, bestRow, bestCol, col + 1)
281 end
282 in swapColLoop (best, bestRow, bestCol, pos)
283 end
284 fun rowLoop row =
285 if row < height
286 then if (matCol row) = zero
287 then rowLoop (row + 1)
288 else (Matrix.rowOp (mat,
289 pos,
290 row,
291 let val x = IntInf.~ (IntInf.quot(matCol row, matCol pos))
292 in fn (lhs, rhs) => IntInf.+ (IntInf.* (lhs, x), rhs)
293 end);
294 if (matCol row) = zero
295 then rowLoop (row + 1)
296 else hitPosAgain ())
297 else let fun colLoop col =
298 if col < width
299 then if (matRow col) = zero
300 then colLoop (col + 1)
301 else (Matrix.colOp (mat,
302 pos,
303 col,
304 let val x = IntInf.~ (IntInf.quot (matRow col, matRow pos))
305 in fn (lhs, rhs) => IntInf.+ (IntInf.* (lhs, x), rhs)
306 end);
307 if (matRow col) = zero
308 then colLoop (col + 1)
309 else hitPosAgain ())
310 else ()
311 in colLoop (pos + 1)
312 end
313 and hitPosAgain () = (swapRowLoop (zero, pos, pos, pos);
314 rowLoop (pos + 1))
315 in hitPosAgain ()
316 end
317 fun loop pos =
318 if pos = range
319 then mat
320 else (dd pos;
321 loop (pos + 1))
322 in loop 0
323 end
324
325val table = [[ 8, ~3, 1, 3, 6, 9, ~2, 4, ~9, ~9, 2, 3, 8, ~1, 3, ~5, 4, ~3, ~5, ~6, 8, 1, 4, ~5, 7, ~4, ~4, ~7, 7, 1, 4, ~3, 8, 4, ~4, ~8, 5, ~9, 3, ~4, 1, 9, ~8, ~6, ~2, 8, ~9, ~5, ~3, ~3],
326 [ 0, 8, ~6, ~2, ~3, 4, 5, ~2, 7, ~7, ~6, ~7, ~3, ~4, 9, 7, ~3, 3, 0, 3, 3, ~8, ~8, 2, 3, 8, 3, ~2, ~4, 3, ~6, ~6, ~2, 6, 5, ~1, ~3, 1, 8, ~8, 2, 1, ~7, ~7, ~7, ~3, ~6, 6, ~4, ~9],
327 [ 0, ~5, 8, ~9, 2, 4, 2, 7, ~4, 9, ~3, 6, ~2, 3, ~3, 0, ~9, 5, 8, ~1, 2, ~8, 3, 4, ~6, 5, ~6, ~5, ~8, 0, ~5, 3, ~2, ~5, 8, 7, ~1, 1, ~1, 7, 6, 3, 6, 5, 6, 8, 7, 9, 7, ~3],
328 [ 5, 4, 7, 2, 3, ~9, 7, ~7, 3, ~8, 7, 5, 5, ~2, ~6, ~3, 6, 5, 3, ~1, ~1, 4, 5, ~5, 5, 9, 9, 3, 8, ~3, ~1, 9, ~9, 6, ~7, 7, 4, 6, ~8, ~9, 0, ~3, ~2, ~7, 1, ~2, ~6, 7, 7, 7],
329 [ 2, 9, 9, 3, ~4, 0, 9, 2, 5, 3, ~5, ~3, ~1, 1, 8, ~6, 2, ~4, ~8, ~7, ~8, 4, 5, 8, ~1, ~1, 7, 2, 5, 5, ~4, ~7, ~3, ~7, 6, ~4, ~5, ~8, ~5, ~9, ~8, 5, ~5, ~5, 0, 8, 8, 6, 4, ~1],
330 [ 5, 5, 1, ~7, 3, ~5, 4, 9, 3, 4, 4, ~5, 7, ~1, 7, 4, ~7, 7, ~7, ~2, 9, ~9, 0, ~4, ~4, 0, 2, 6, 3, ~1, 6, 6, 8, ~6, ~4, ~9, 3, ~2, ~5, 5, ~3, 2, ~1, ~6, 9, 3, ~3, ~8, ~9, 7],
331 [ 7, 1, 2, 7, 6, 5, ~6, ~3, ~4, ~8, 0, 9, 6, 1, 2, ~5, 4, 4, 4, ~6, ~7, ~9, ~6, 2, ~4, 5, ~2, 1, 0, 1, ~8, 7, ~7, ~5, 4, 1, ~5, 4, ~4, ~2, ~3, 1, 1, 3, 4, ~4, ~5, 9, 8, ~2],
332 [ 6, 2, ~1, ~8, 4, ~7, 7, ~3, ~2, ~5, 3, 0, 3, ~9, 3, 3, 9, ~1, 4, 8, ~9, 6, ~5, 9, 5, ~1, ~1, ~9, 7, ~2, 3, 9, 8, 9, 2, 7, 7, 6, ~1, ~1, ~2, ~2, ~7, 3, ~6, 0, ~9, 4, 3, 7],
333 [ 0, ~6, ~3, ~7, ~1, 5, ~2, 8, ~5, ~3, ~8, 7, ~2, ~2, 0, ~8, 4, 8, 9, ~5, ~4, ~8, ~1, 7, 1, 1, 6, ~9, ~4, 0, 8, 4, 3, ~7, 6, 0, 1, 8, 6, ~1, ~1, ~7, 9, ~9, ~5, ~2, ~2, ~1, 1, 0],
334 [~4, 9, 6, ~3, ~2, ~6, ~3, 4, 8, ~8, 1, ~5, 9, 7, 9, 7, ~9, ~6, 6, 1, ~3, 3, ~3, ~7, 1, 7, ~7, 0, ~2, 7, ~4, ~6, 0, 1, ~3, ~5, ~9, ~7, 8, 4, 9, ~8, ~8, ~7, ~6, 7, 6, ~3, ~8, 5],
335 [ 6, 7, ~5, ~9, 6, 1, 8, 4, ~2, 7, ~7, ~1, ~9, 1, ~6, ~5, 4, 9, 6, 0, ~8, ~3, 1, ~3, 8, ~3, 2, 9, ~3, ~9, ~1, ~3, 4, 3, 2, ~9, ~5, ~3, 8, ~4, 8, 5, ~4, 7, 6, ~8, 7, 6, ~5, 5],
336 [ 1, 7, ~8, ~9, ~7, ~3, 8, 9, ~7, ~1, ~7, 4, 0, 0, 1, ~5, 9, ~8, ~1, ~2, 3, 5, 9, ~9, 5, 4, ~9, 1, ~4, ~2, 3, ~4, 8, ~6, ~4, ~8, ~5, ~5, 4, ~2, ~4, ~1, ~9, ~5, 2, ~9, 2, ~9, ~2, ~3],
337 [~5, ~4, ~4, 9, 2, 7, ~2, 6, 7, 2, ~9, 4, 2, 7, 8, ~9, 2, 5, 3, 9, 6, 3, 0, ~7, ~6, ~7, 6, ~2, 9, ~3, ~6, 9, ~9, 2, 2, ~6, ~1, 4, ~3, 3, 0, 6, ~3, 4, 9, 9, ~6, 5, 5, ~5],
338 [ 5, ~7, 8, ~4, 8, 8, ~4, ~9, 6, 0, ~3, 6, 0, 8, 8, ~6, ~2, 5, 4, ~1, ~8, 1, ~3, ~1, 2, 3, ~9, ~9, ~5, 1, 8, ~5, ~3, 0, ~4, ~9, 0, ~6, 3, ~1, ~7, 0, 8, 9, ~6, ~1, ~9, 1, ~6, 2],
339 [ 7, ~5, ~1, 5, ~2, 7, 0, ~7, ~1, 8, 8, ~3, 9, ~5, 7, ~8, ~8, ~4, 3, 2, ~1, 8, ~2, 1, 2, 5, 0, ~6, 7, 3, 3, 7, ~5, 5, ~1, 1, 0, ~8, 1, 0, 0, ~4, 6, 9, ~5, ~6, 3, ~5, 8, 5],
340 [~4, ~2, 3, ~3, ~1, 2, ~2, ~1, ~9, ~5, 1, 0, 0, 2, 9, ~3, ~9, 2, 9, 3, 8, ~3, 4, 8, 8, 3, ~3, ~1, ~4, 4, ~6, ~9, 5, ~2, 1, 3, ~7, ~5, ~6, ~5, ~8, 4, ~8, ~3, 5, 0, 7, ~9, 6, 2],
341 [ 5, 1, 4, ~3, ~1, ~9, 5, ~8, ~8, 6, 1, 1, ~2, 7, 5, 6, ~4, 2, ~7, 0, ~7, ~3, ~5, 9, 3, 4, ~6, 8, ~4, 3, 6, 0, 2, 3, ~6, 3, 9, 4, 1, ~4, 6, ~5, ~7, 0, ~1, ~8, ~3, ~9, 9, 7],
342 [ 2, ~6, ~1, 8, 4, ~3, ~1, ~6, ~2, ~8, ~2, ~1, ~1, ~5, ~9, ~8, 9, ~9, 5, 1, 9, ~1, ~6, 9, ~7, 2, 8, ~7, 4, ~9, 7, 6, ~2, 1, ~2, ~7, 8, 0, 5, 0, ~5, ~7, ~6, 0, 4, 0, 3, ~8, 5, 4],
343 [~2, 9, ~9, ~6, 1, ~8, 8, 4, ~6, 8, 1, ~3, ~7, 8, ~5, 2, ~8, 1, 3, ~2, 6, 6, 6, 1, 0, 0, ~7, 7, ~3, ~3, 0, ~4, 3, ~7, ~6, 7, 5, 9, ~5, 7, ~8, 2, 3, ~8, ~7, 6, ~5, ~5, ~8, ~9],
344 [~7, ~4, 4, 1, ~1, ~3, ~8, 3, 7, 9, 8, 3, 0, 4, 4, ~1, ~5, 4, 2, 2, 0, 6, ~6, 2, ~9, 8, ~9, 3, ~2, 2, 6, 6, 1, 7, 1, 0, ~8, 2, 3, ~3, 8, 9, 5, 5, ~6, 4, ~7, ~4, ~2, ~3],
345 [~5, 8, 6, 1, ~6, ~6, 6, 1, 1, ~3, ~9, ~6, 2, ~7, 2, ~1, 6, ~6, 0, 2, ~7, 8, ~8, 4, 9, ~3, 9, ~7, ~9, ~6, ~4, ~4, ~5, 8, 2, ~5, ~4, ~3, 5, 2, 1, ~3, ~3, ~7, ~9, 3, 7, ~7, 3, ~8],
346 [~4, ~7, ~2, 2, ~4, ~2, 6, ~3, ~1, ~4, 0, ~5, 9, 7, ~6, ~9, 7, ~9, ~6, 2, ~3, 1, 5, ~9, 4, ~5, 4, ~9, 1, ~2, ~2, 4, 0, 4, ~8, ~8, 3, ~1, ~5, ~4, ~9, ~7, 7, 6, 3, ~9, 6, 4, ~4, ~7],
347 [~9, 6, 6, ~5, ~1, ~7, 4, ~9, 4, ~1, 6, ~4, 7, 2, 8, 7, 3, 1, ~7, 7, 7, 9, 8, ~9, 7, 2, 1, 2, ~8, 4, 5, 6, 7, 2, ~7, 6, 8, 4, ~9, 7, ~5, 6, 9, ~1, 9, 2, 0, 9, 3, 6],
348 [ 4, ~3, 8, 0, ~2, ~2, 2, ~3, 8, 3, 1, ~8, ~5, ~2, 5, 6, 8, 0, ~3, 4, ~2, 4, ~9, ~5, 7, 6, ~4, ~7, 2, 4, ~3, ~8, ~9, 9, 8, ~9, 3, ~7, 4, ~7, ~5, 4, 9, 3, ~6, ~3, ~7, 4, 2, ~2],
349 [~8, ~8, 6, ~2, ~6, 8, ~3, 3, ~1, ~7, 1, 9, 1, 7, ~6, 8, ~2, ~9, ~1, 3, ~4, 7, 8, ~1, 9, ~9, 6, ~3, 5, 0, 2, 5, ~1, ~6, ~6, 1, 8, 6, ~3, ~9, ~1, 9, ~2, 9, ~8, ~7, ~3, 6, ~3, ~3],
350 [ 5, ~2, 3, 0, ~9, ~8, ~6, 1, 8, 0, 1, 2, ~8, ~2, 0, ~9, ~8, 0, 5, ~3, ~4, 5, 6, ~2, ~5, 0, ~9, 9, ~9, ~5, 9, 9, ~5, ~2, 4, 3, 8, ~8, ~7, 5, ~3, ~2, 2, 3, 9, 7, ~1, 0, 4, ~1],
351 [~4, 5, ~5, 7, 8, 9, 7, ~3, 1, 9, ~7, ~1, 8, ~5, ~1, 2, ~8, 1, 0, 9, ~8, ~1, 6, ~1, 9, ~8, 7, 4, ~8, 7, 0, ~6, 2, 3, 7, 4, ~3, ~5, 9, ~3, 0, 6, ~9, 2, 4, ~8, 6, ~7, 9, 1],
352 [ 7, 0, ~9, 6, 8, 2, 2, 5, ~6, ~6, 9, ~5, 9, 2, 2, ~8, 0, ~6, ~9, ~6, ~4, ~9, 8, ~2, 9, 7, ~5, ~1, 7, 2, ~7, 7, ~1, ~3, 6, 6, 1, ~4, 0, ~1, ~6, ~5, 6, ~7, ~3, ~2, 8, 2, ~9, 8],
353 [ 8, ~7, ~9, ~6, 9, ~7, ~7, 6, ~8, 9, 5, ~4, 1, ~7, ~8, ~6, ~3, 8, ~8, 1, ~8, 6, 9, ~3, ~7, 7, 1, 6, 1, 0, 8, ~5, ~8, 8, ~9, 0, 4, 4, 3, ~4, 6, ~3, ~9, 0, 4, ~4, ~5, ~9, ~5, ~8],
354 [~3, ~2, 8, 1, ~1, ~1, ~4, 3, 7, ~2, ~9, 9, ~8, ~9, 6, ~4, 7, ~1, ~5, ~3, ~9, 0, ~3, 0, 7, 9, 1, ~2, 7, ~9, ~6, 3, 3, ~4, ~7, ~3, ~4, ~8, ~2, ~3, ~9, ~2, ~6, 3, ~6, ~4, 7, ~5, ~8, ~1],
355 [~9, ~9, ~2, ~9, ~9, 9, 6, 6, 7, 5, ~1, ~2, 1, 5, 2, ~3, ~4, 1, ~6, 0, ~3, ~9, ~1, 7, 0, ~9, 5, ~2, ~2, 5, 3, 4, ~1, 6, ~6, 3, ~6, 7, ~1, 5, ~8, ~4, ~2, ~2, ~6, ~5, ~6, 3, ~1, 4],
356 [ 7, 7, 8, 7, 6, 1, ~2, 5, ~6, 9, 4, 8, 5, 0, ~4, ~2, ~2, ~5, ~2, ~6, 9, ~8, ~2, ~5, ~9, 3, ~6, ~3, ~4, ~5, ~2, 6, 1, 6, ~5, 0, ~3, ~2, 4, ~6, 1, 6, ~1, 3, ~9, 2, ~3, 1, 5, ~6],
357 [ 6, 4, ~7, 3, ~7, 9, 1, ~7, ~8, 0, ~6, 8, 4, 1, 9, 6, 8, 3, 0, 9, 0, 4, 9, ~7, ~7, 1, 5, 1, ~5, 6, 9, 2, 4, 1, ~9, 8, 4, 5, 8, 3, 2, ~9, ~6, ~9, 9, ~9, 7, ~6, ~4, 3],
358 [~3, ~9, ~4, 2, 3, 9, ~9, 8, ~9, 9, ~4, ~9, ~5, 5, 0, 7, 3, ~5, ~8, 2, ~3, 0, ~9, ~3, 1, 9, 4, 5, ~1, 8, 0, ~4, ~2, 9, ~4, ~1, 3, 5, 9, ~1, 1, 4, ~8, ~2, ~3, 5, 1, 5, ~6, 7],
359 [ 9, ~3, 2, ~9, 3, 4, 0, 7, ~5, 9, 0, ~6, 7, ~2, 3, ~7, 2, ~5, ~2, 6, 3, ~9, ~5, ~9, 5, 2, ~5, ~3, 8, ~5, 6, 2, 9, ~7, ~7, ~7, ~6, 9, ~3, 6, 0, 6, ~6, ~9, 4, ~3, ~9, 0, ~4, ~9],
360 [~4, ~8, 8, ~7, 7, 0, ~6, ~6, 8, ~9, ~4, 5, ~3, ~1, 7, ~5, ~6, ~1, 8, 6, ~2, 1, ~1, 5, ~9, 1, ~1, ~7, ~6, ~6, ~6, ~4, 6, 3, ~5, ~5, ~6, 2, 3, ~6, ~8, ~3, 8, ~2, ~5, ~4, ~3, 1, 4, ~4],
361 [ 4, ~6, 2, 6, 2, ~8, 8, 5, 8, ~2, 0, ~6, ~1, ~6, ~2, 2, 6, ~9, ~7, ~6, ~4, ~4, ~7, ~2, 8, 6, 3, ~7, ~6, 8, 2, 3, 4, 5, 3, 4, ~6, 8, 8, ~1, 4, ~5, 6, 2, 8, ~3, ~9, ~2, 6, 7],
362 [ 3, ~4, 0, ~3, ~5, 0, ~2, ~6, ~2, 8, 5, ~9, ~4, ~8, ~6, 0, 8, 9, 1, ~2, 8, 2, ~2, 8, 9, 3, 3, 5, ~9, ~3, ~2, 7, 2, 9, 0, 4, 8, ~9, 0, ~6, 9, ~9, 9, ~4, 8, ~8, ~8, 2, ~3, 2],
363 [~1, 3, ~9, ~8, ~7, 6, ~6, 3, 0, 5, ~5, 1, 2, ~2, ~3, 7, 7, 3, ~4, ~2, ~9, ~5, ~1, 9, 6, 8, 2, 8, 7, ~3, 4, 6, 6, 0, ~2, 2, ~7, ~7, 6, ~3, 8, 2, 1, 0, 8, ~1, 3, 9, 8, 6],
364 [ 1, ~2, ~3, 6, 5, 5, ~6, ~4, ~5, 1, 1, 6, ~7, ~4, ~3, 4, 4, ~8, ~9, 7, ~2, ~3, ~7, ~2, 1, 2, 0, 8, ~6, ~5, ~5, 7, 8, 5, ~2, 3, 9, 0, 5, 1, 3, ~4, ~6, 1, 4, ~9, ~2, 5, 4, 3],
365 [ 3, 3, 9, ~2, 6, 9, 4, 9, 4, ~8, 5, ~1, 3, ~2, 1, ~7, ~3, 2, 2, 0, ~3, 3, 8, 2, 0, ~5, 7, 1, 4, ~8, 8, ~9, ~1, 1, ~9, ~4, 5, 2, 2, 8, 6, 1, 6, ~2, 2, 7, 1, ~6, ~1, ~1],
366 [ 4, ~2, 4, ~1, ~5, ~1, 5, ~2, 3, ~4, ~5, 0, 2, ~4, 6, 4, ~3, 2, 2, 5, ~6, ~7, ~9, ~1, ~9, ~9, 6, 0, 6, 5, 9, ~1, 3, ~3, ~8, 8, ~8, 8, 4, 5, ~1, ~5, 1, 0, 3, ~2, 5, 6, 6, 5],
367 [~4, 9, 6, 8, ~9, 5, 5, ~3, ~7, 7, 6, 8, ~8, 0, 4, ~1, 9, 5, ~7, 0, ~1, ~2, 3, 6, 0, 4, ~3, 1, 4, 6, 4, 0, 5, ~1, 7, ~7, ~6, ~8, ~3, ~6, 7, ~1, ~3, ~2, ~3, ~5, 3, 1, ~8, ~9],
368 [~6, 4, ~5, 9, 9, ~7, ~1, ~8, ~4, 2, ~6, 0, ~6, ~6, 7, 6, 0, 1, 7, ~7, 0, ~4, ~6, ~8, ~9, 5, ~6, ~9, 2, ~7, ~2, ~6, 9, 4, ~5, 0, 4, ~4, ~5, 6, 9, 1, ~6, ~5, 3, ~1, 7, ~7, ~6, 7],
369 [~8, 7, 7, ~6, 7, ~4, 8, 0, ~9, ~8, ~3, 7, ~3, 3, 8, ~7, ~2, ~7, 5, 5, ~5, 4, 6, 2, 4, 1, 4, ~9, ~3, 8, 8, ~9, ~4, ~2, 1, ~3, 1, 3, 9, ~5, ~8, ~2, 7, 8, 9, 2, 0, 1, ~9, 6],
370 [~7, 1, ~9, 5, ~5, ~5, 7, 6, ~5, ~9, ~6, ~8, ~6, 9, 7, 9, 0, ~5, 7, 7, ~6, 4, 5, ~9, ~1, ~2, ~7, 3, ~5, ~2, ~5, 5, ~3, ~4, ~2, ~8, 2, ~8, 0, ~8, 0, ~8, 9, 8, ~5, ~5, 1, 3, 5, ~4],
371 [~8, ~8, 0, ~5, ~8, ~6, 3, ~6, ~4, 6, 1, ~5, ~6, ~8, ~4, ~6, ~2, ~6, 6, ~4, 8, 8, 4, ~5, ~1, 0, 9, ~8, ~3, ~1, ~8, 7, ~3, 0, ~7, 1, ~7, ~1, ~7, 3, ~7, 3, ~4, ~8, 8, ~7, ~9, ~8, 3, 2],
372 [ 3, 6, 8, ~9, 7, 1, ~9, 9, 3, 8, 6, 4, ~2, 1, ~8, 4, ~7, ~4, ~3, 3, ~5, ~6, ~7, ~2, 0, ~4, 5, 2, 5, 6, 3, ~8, 2, ~5, ~7, 6, 8, ~2, ~5, ~4, 9, 9, 2, ~2, ~2, 7, 4, 4, ~2, 3],
373 [ 6, 6, ~5, ~2, ~8, ~2, ~9, 0, 2, 4, ~6, ~9, 9, 0, ~8, ~3, ~1, ~2, ~1, 6, 8, 2, ~9, 5, ~2, 1, 7, ~6, 5, 1, ~1, 4, ~4, ~7, ~6, ~3, ~8, 2, 2, 5, 5, ~6, 5, 3, 3, 7, 4, 7, ~3, ~9],
374 [~9, 6, ~4, 1, 3, ~8, ~8, ~8, ~1, 5, 1, 1, ~1, 6, 5, 1, ~1, 5, ~8, 8, ~7, ~5, ~1, ~1, 6, ~8, ~3, ~1, ~2, ~6, ~5, ~5, ~6, 0, 2, 2, 7, ~1, ~5, ~7, ~1, ~3, 7, 6, 0, 2, 4, ~5, 0, ~4]]
375
376fun f (x, y) = List.nth (List.nth (table, x), y)
377fun show m = print (Matrix.toString (m, IntInf.toString))
378val _ =
379 let val dim = 32
380 val big = Matrix.map (Matrix.make (dim, dim, f), IntInf.fromInt)
381 in show big;
382 print "\n";
383 show (smithNormalForm big)
384 end
385