Mercurial > hg > sv-dependency-builds
comparison src/fftw-3.3.8/genfft/algsimp.ml @ 167:bd3cc4d1df30
Add FFTW 3.3.8 source, and a Linux build
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 19 Nov 2019 14:52:55 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
166:cbd6d7e562c7 | 167:bd3cc4d1df30 |
---|---|
1 (* | |
2 * Copyright (c) 1997-1999 Massachusetts Institute of Technology | |
3 * Copyright (c) 2003, 2007-14 Matteo Frigo | |
4 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 * | |
20 *) | |
21 | |
22 | |
23 open Util | |
24 open Expr | |
25 | |
26 let node_insert x = Assoctable.insert Expr.hash x | |
27 let node_lookup x = Assoctable.lookup Expr.hash (==) x | |
28 | |
29 (************************************************************* | |
30 * Algebraic simplifier/elimination of common subexpressions | |
31 *************************************************************) | |
32 module AlgSimp : sig | |
33 val algsimp : expr list -> expr list | |
34 end = struct | |
35 | |
36 open Monads.StateMonad | |
37 open Monads.MemoMonad | |
38 open Assoctable | |
39 | |
40 let fetchSimp = | |
41 fetchState >>= fun (s, _) -> returnM s | |
42 let storeSimp s = | |
43 fetchState >>= (fun (_, c) -> storeState (s, c)) | |
44 let lookupSimpM key = | |
45 fetchSimp >>= fun table -> | |
46 returnM (node_lookup key table) | |
47 let insertSimpM key value = | |
48 fetchSimp >>= fun table -> | |
49 storeSimp (node_insert key value table) | |
50 | |
51 let subset a b = | |
52 List.for_all (fun x -> List.exists (fun y -> x == y) b) a | |
53 | |
54 let structurallyEqualCSE a b = | |
55 match (a, b) with | |
56 | (Num a, Num b) -> Number.equal a b | |
57 | (NaN a, NaN b) -> a == b | |
58 | (Load a, Load b) -> Variable.same a b | |
59 | (Times (a, a'), Times (b, b')) -> | |
60 ((a == b) && (a' == b')) || | |
61 ((a == b') && (a' == b)) | |
62 | (CTimes (a, a'), CTimes (b, b')) -> | |
63 ((a == b) && (a' == b')) || | |
64 ((a == b') && (a' == b)) | |
65 | (CTimesJ (a, a'), CTimesJ (b, b')) -> ((a == b) && (a' == b')) | |
66 | (Plus a, Plus b) -> subset a b && subset b a | |
67 | (Uminus a, Uminus b) -> (a == b) | |
68 | _ -> false | |
69 | |
70 let hashCSE x = | |
71 if (!Magic.randomized_cse) then | |
72 Oracle.hash x | |
73 else | |
74 Expr.hash x | |
75 | |
76 let equalCSE a b = | |
77 if (!Magic.randomized_cse) then | |
78 (structurallyEqualCSE a b || Oracle.likely_equal a b) | |
79 else | |
80 structurallyEqualCSE a b | |
81 | |
82 let fetchCSE = | |
83 fetchState >>= fun (_, c) -> returnM c | |
84 let storeCSE c = | |
85 fetchState >>= (fun (s, _) -> storeState (s, c)) | |
86 let lookupCSEM key = | |
87 fetchCSE >>= fun table -> | |
88 returnM (Assoctable.lookup hashCSE equalCSE key table) | |
89 let insertCSEM key value = | |
90 fetchCSE >>= fun table -> | |
91 storeCSE (Assoctable.insert hashCSE key value table) | |
92 | |
93 (* memoize both x and Uminus x (unless x is already negated) *) | |
94 let identityM x = | |
95 let memo x = memoizing lookupCSEM insertCSEM returnM x in | |
96 match x with | |
97 Uminus _ -> memo x | |
98 | _ -> memo x >>= fun x' -> memo (Uminus x') >> returnM x' | |
99 | |
100 let makeNode = identityM | |
101 | |
102 (* simplifiers for various kinds of nodes *) | |
103 let rec snumM = function | |
104 n when Number.is_zero n -> | |
105 makeNode (Num (Number.zero)) | |
106 | n when Number.negative n -> | |
107 makeNode (Num (Number.negate n)) >>= suminusM | |
108 | n -> makeNode (Num n) | |
109 | |
110 and suminusM = function | |
111 Uminus x -> makeNode x | |
112 | Num a when (Number.is_zero a) -> snumM Number.zero | |
113 | a -> makeNode (Uminus a) | |
114 | |
115 and stimesM = function | |
116 | (Uminus a, b) -> stimesM (a, b) >>= suminusM | |
117 | (a, Uminus b) -> stimesM (a, b) >>= suminusM | |
118 | (NaN I, CTimes (a, b)) -> stimesM (NaN I, b) >>= | |
119 fun ib -> sctimesM (a, ib) | |
120 | (NaN I, CTimesJ (a, b)) -> stimesM (NaN I, b) >>= | |
121 fun ib -> sctimesjM (a, ib) | |
122 | (Num a, Num b) -> snumM (Number.mul a b) | |
123 | (Num a, Times (Num b, c)) -> | |
124 snumM (Number.mul a b) >>= fun x -> stimesM (x, c) | |
125 | (Num a, b) when Number.is_zero a -> snumM Number.zero | |
126 | (Num a, b) when Number.is_one a -> makeNode b | |
127 | (Num a, b) when Number.is_mone a -> suminusM b | |
128 | (a, b) when is_known_constant b && not (is_known_constant a) -> | |
129 stimesM (b, a) | |
130 | (a, b) -> makeNode (Times (a, b)) | |
131 | |
132 and sctimesM = function | |
133 | (Uminus a, b) -> sctimesM (a, b) >>= suminusM | |
134 | (a, Uminus b) -> sctimesM (a, b) >>= suminusM | |
135 | (a, b) -> makeNode (CTimes (a, b)) | |
136 | |
137 and sctimesjM = function | |
138 | (Uminus a, b) -> sctimesjM (a, b) >>= suminusM | |
139 | (a, Uminus b) -> sctimesjM (a, b) >>= suminusM | |
140 | (a, b) -> makeNode (CTimesJ (a, b)) | |
141 | |
142 and reduce_sumM x = match x with | |
143 [] -> returnM [] | |
144 | [Num a] -> | |
145 if (Number.is_zero a) then | |
146 returnM [] | |
147 else returnM x | |
148 | [Uminus (Num a)] -> | |
149 if (Number.is_zero a) then | |
150 returnM [] | |
151 else returnM x | |
152 | (Num a) :: (Num b) :: s -> | |
153 snumM (Number.add a b) >>= fun x -> | |
154 reduce_sumM (x :: s) | |
155 | (Num a) :: (Uminus (Num b)) :: s -> | |
156 snumM (Number.sub a b) >>= fun x -> | |
157 reduce_sumM (x :: s) | |
158 | (Uminus (Num a)) :: (Num b) :: s -> | |
159 snumM (Number.sub b a) >>= fun x -> | |
160 reduce_sumM (x :: s) | |
161 | (Uminus (Num a)) :: (Uminus (Num b)) :: s -> | |
162 snumM (Number.add a b) >>= | |
163 suminusM >>= fun x -> | |
164 reduce_sumM (x :: s) | |
165 | ((Num _) as a) :: b :: s -> reduce_sumM (b :: a :: s) | |
166 | ((Uminus (Num _)) as a) :: b :: s -> reduce_sumM (b :: a :: s) | |
167 | a :: s -> | |
168 reduce_sumM s >>= fun s' -> returnM (a :: s') | |
169 | |
170 and collectible1 = function | |
171 | NaN _ -> false | |
172 | Uminus x -> collectible1 x | |
173 | _ -> true | |
174 and collectible (a, b) = collectible1 a | |
175 | |
176 (* collect common factors: ax + bx -> (a+b)x *) | |
177 and collectM which x = | |
178 let rec findCoeffM which = function | |
179 | Times (a, b) when collectible (which (a, b)) -> returnM (which (a, b)) | |
180 | Uminus x -> | |
181 findCoeffM which x >>= fun (coeff, b) -> | |
182 suminusM coeff >>= fun mcoeff -> | |
183 returnM (mcoeff, b) | |
184 | x -> snumM Number.one >>= fun one -> returnM (one, x) | |
185 and separateM xpr = function | |
186 [] -> returnM ([], []) | |
187 | a :: b -> | |
188 separateM xpr b >>= fun (w, wo) -> | |
189 (* try first factor *) | |
190 findCoeffM (fun (a, b) -> (a, b)) a >>= fun (c, x) -> | |
191 if (xpr == x) && collectible (c, x) then returnM (c :: w, wo) | |
192 else | |
193 (* try second factor *) | |
194 findCoeffM (fun (a, b) -> (b, a)) a >>= fun (c, x) -> | |
195 if (xpr == x) && collectible (c, x) then returnM (c :: w, wo) | |
196 else returnM (w, a :: wo) | |
197 in match x with | |
198 [] -> returnM x | |
199 | [a] -> returnM x | |
200 | a :: b -> | |
201 findCoeffM which a >>= fun (_, xpr) -> | |
202 separateM xpr x >>= fun (w, wo) -> | |
203 collectM which wo >>= fun wo' -> | |
204 splusM w >>= fun w' -> | |
205 stimesM (w', xpr) >>= fun t' -> | |
206 returnM (t':: wo') | |
207 | |
208 and mangleSumM x = returnM x | |
209 >>= reduce_sumM | |
210 >>= collectM (fun (a, b) -> (a, b)) | |
211 >>= collectM (fun (a, b) -> (b, a)) | |
212 >>= reduce_sumM | |
213 >>= deepCollectM !Magic.deep_collect_depth | |
214 >>= reduce_sumM | |
215 | |
216 and reorder_uminus = function (* push all Uminuses to the end *) | |
217 [] -> [] | |
218 | ((Uminus _) as a' :: b) -> (reorder_uminus b) @ [a'] | |
219 | (a :: b) -> a :: (reorder_uminus b) | |
220 | |
221 and canonicalizeM = function | |
222 [] -> snumM Number.zero | |
223 | [a] -> makeNode a (* one term *) | |
224 | a -> generateFusedMultAddM (reorder_uminus a) | |
225 | |
226 and generateFusedMultAddM = | |
227 let rec is_multiplication = function | |
228 | Times (Num a, b) -> true | |
229 | Uminus (Times (Num a, b)) -> true | |
230 | _ -> false | |
231 and separate = function | |
232 [] -> ([], [], Number.zero) | |
233 | (Times (Num a, b)) as this :: c -> | |
234 let (x, y, max) = separate c in | |
235 let newmax = if (Number.greater a max) then a else max in | |
236 (this :: x, y, newmax) | |
237 | (Uminus (Times (Num a, b))) as this :: c -> | |
238 let (x, y, max) = separate c in | |
239 let newmax = if (Number.greater a max) then a else max in | |
240 (this :: x, y, newmax) | |
241 | this :: c -> | |
242 let (x, y, max) = separate c in | |
243 (x, this :: y, max) | |
244 in fun l -> | |
245 if !Magic.enable_fma && count is_multiplication l >= 2 then | |
246 let (w, wo, max) = separate l in | |
247 snumM (Number.div Number.one max) >>= fun invmax' -> | |
248 snumM max >>= fun max' -> | |
249 mapM (fun x -> stimesM (invmax', x)) w >>= splusM >>= fun pw' -> | |
250 stimesM (max', pw') >>= fun mw' -> | |
251 splusM (wo @ [mw']) | |
252 else | |
253 makeNode (Plus l) | |
254 | |
255 | |
256 and negative = function | |
257 Uminus _ -> true | |
258 | _ -> false | |
259 | |
260 (* | |
261 * simplify patterns of the form | |
262 * | |
263 * ((c_1 * a + ...) + ...) + (c_2 * a + ...) | |
264 * | |
265 * The pattern includes arbitrary coefficients and minus signs. | |
266 * A common case of this pattern is the butterfly | |
267 * (a + b) + (a - b) | |
268 * (a + b) - (a - b) | |
269 *) | |
270 (* this whole procedure needs much more thought *) | |
271 and deepCollectM maxdepth l = | |
272 let rec findTerms depth x = match x with | |
273 | Uminus x -> findTerms depth x | |
274 | Times (Num _, b) -> (findTerms (depth - 1) b) | |
275 | Plus l when depth > 0 -> | |
276 x :: List.flatten (List.map (findTerms (depth - 1)) l) | |
277 | x -> [x] | |
278 and duplicates = function | |
279 [] -> [] | |
280 | a :: b -> if List.memq a b then a :: duplicates b | |
281 else duplicates b | |
282 | |
283 in let rec splitDuplicates depth d x = | |
284 if (List.memq x d) then | |
285 snumM (Number.zero) >>= fun zero -> | |
286 returnM (zero, x) | |
287 else match x with | |
288 | Times (a, b) -> | |
289 splitDuplicates (depth - 1) d a >>= fun (a', xa) -> | |
290 splitDuplicates (depth - 1) d b >>= fun (b', xb) -> | |
291 stimesM (a', b') >>= fun ab -> | |
292 stimesM (a, xb) >>= fun xb' -> | |
293 stimesM (xa, b) >>= fun xa' -> | |
294 stimesM (xa, xb) >>= fun xab -> | |
295 splusM [xa'; xb'; xab] >>= fun x -> | |
296 returnM (ab, x) | |
297 | Uminus a -> | |
298 splitDuplicates depth d a >>= fun (x, y) -> | |
299 suminusM x >>= fun ux -> | |
300 suminusM y >>= fun uy -> | |
301 returnM (ux, uy) | |
302 | Plus l when depth > 0 -> | |
303 mapM (splitDuplicates (depth - 1) d) l >>= fun ld -> | |
304 let (l', d') = List.split ld in | |
305 splusM l' >>= fun p -> | |
306 splusM d' >>= fun d'' -> | |
307 returnM (p, d'') | |
308 | x -> | |
309 snumM (Number.zero) >>= fun zero' -> | |
310 returnM (x, zero') | |
311 | |
312 in let l' = List.flatten (List.map (findTerms maxdepth) l) | |
313 in match duplicates l' with | |
314 | [] -> returnM l | |
315 | d -> | |
316 mapM (splitDuplicates maxdepth d) l >>= fun ld -> | |
317 let (l', d') = List.split ld in | |
318 splusM l' >>= fun l'' -> | |
319 let rec flattenPlusM = function | |
320 | Plus l -> returnM l | |
321 | Uminus x -> | |
322 flattenPlusM x >>= mapM suminusM | |
323 | x -> returnM [x] | |
324 in | |
325 mapM flattenPlusM d' >>= fun d'' -> | |
326 splusM (List.flatten d'') >>= fun d''' -> | |
327 mangleSumM [l''; d'''] | |
328 | |
329 and splusM l = | |
330 let fma_heuristics x = | |
331 if !Magic.enable_fma then | |
332 match x with | |
333 | [Uminus (Times _); Times _] -> Some false | |
334 | [Times _; Uminus (Times _)] -> Some false | |
335 | [Uminus (_); Times _] -> Some true | |
336 | [Times _; Uminus (Plus _)] -> Some true | |
337 | [_; Uminus (Times _)] -> Some false | |
338 | [Uminus (Times _); _] -> Some false | |
339 | _ -> None | |
340 else | |
341 None | |
342 in | |
343 mangleSumM l >>= fun l' -> | |
344 (* no terms are negative. Don't do anything *) | |
345 if not (List.exists negative l') then | |
346 canonicalizeM l' | |
347 (* all terms are negative. Negate them all and collect the minus sign *) | |
348 else if List.for_all negative l' then | |
349 mapM suminusM l' >>= splusM >>= suminusM | |
350 else match fma_heuristics l' with | |
351 | Some true -> mapM suminusM l' >>= splusM >>= suminusM | |
352 | Some false -> canonicalizeM l' | |
353 | None -> | |
354 (* Ask the Oracle for the canonical form *) | |
355 if (not !Magic.randomized_cse) && | |
356 Oracle.should_flip_sign (Plus l') then | |
357 mapM suminusM l' >>= splusM >>= suminusM | |
358 else | |
359 canonicalizeM l' | |
360 | |
361 (* monadic style algebraic simplifier for the dag *) | |
362 let rec algsimpM x = | |
363 memoizing lookupSimpM insertSimpM | |
364 (function | |
365 | Num a -> snumM a | |
366 | NaN _ as x -> makeNode x | |
367 | Plus a -> | |
368 mapM algsimpM a >>= splusM | |
369 | Times (a, b) -> | |
370 (algsimpM a >>= fun a' -> | |
371 algsimpM b >>= fun b' -> | |
372 stimesM (a', b')) | |
373 | CTimes (a, b) -> | |
374 (algsimpM a >>= fun a' -> | |
375 algsimpM b >>= fun b' -> | |
376 sctimesM (a', b')) | |
377 | CTimesJ (a, b) -> | |
378 (algsimpM a >>= fun a' -> | |
379 algsimpM b >>= fun b' -> | |
380 sctimesjM (a', b')) | |
381 | Uminus a -> | |
382 algsimpM a >>= suminusM | |
383 | Store (v, a) -> | |
384 algsimpM a >>= fun a' -> | |
385 makeNode (Store (v, a')) | |
386 | Load _ as x -> makeNode x) | |
387 x | |
388 | |
389 let initialTable = (empty, empty) | |
390 let simp_roots = mapM algsimpM | |
391 let algsimp = runM initialTable simp_roots | |
392 end | |
393 | |
394 (************************************************************* | |
395 * Network transposition algorithm | |
396 *************************************************************) | |
397 module Transpose = struct | |
398 open Monads.StateMonad | |
399 open Monads.MemoMonad | |
400 open Littlesimp | |
401 | |
402 let fetchDuals = fetchState | |
403 let storeDuals = storeState | |
404 | |
405 let lookupDualsM key = | |
406 fetchDuals >>= fun table -> | |
407 returnM (node_lookup key table) | |
408 | |
409 let insertDualsM key value = | |
410 fetchDuals >>= fun table -> | |
411 storeDuals (node_insert key value table) | |
412 | |
413 let rec visit visited vtable parent_table = function | |
414 [] -> (visited, parent_table) | |
415 | node :: rest -> | |
416 match node_lookup node vtable with | |
417 | Some _ -> visit visited vtable parent_table rest | |
418 | None -> | |
419 let children = match node with | |
420 | Store (v, n) -> [n] | |
421 | Plus l -> l | |
422 | Times (a, b) -> [a; b] | |
423 | CTimes (a, b) -> [a; b] | |
424 | CTimesJ (a, b) -> [a; b] | |
425 | Uminus x -> [x] | |
426 | _ -> [] | |
427 in let rec loop t = function | |
428 [] -> t | |
429 | a :: rest -> | |
430 (match node_lookup a t with | |
431 None -> loop (node_insert a [node] t) rest | |
432 | Some c -> loop (node_insert a (node :: c) t) rest) | |
433 in | |
434 (visit | |
435 (node :: visited) | |
436 (node_insert node () vtable) | |
437 (loop parent_table children) | |
438 (children @ rest)) | |
439 | |
440 let make_transposer parent_table = | |
441 let rec termM node candidate_parent = | |
442 match candidate_parent with | |
443 | Store (_, n) when n == node -> | |
444 dualM candidate_parent >>= fun x' -> returnM [x'] | |
445 | Plus (l) when List.memq node l -> | |
446 dualM candidate_parent >>= fun x' -> returnM [x'] | |
447 | Times (a, b) when b == node -> | |
448 dualM candidate_parent >>= fun x' -> | |
449 returnM [makeTimes (a, x')] | |
450 | CTimes (a, b) when b == node -> | |
451 dualM candidate_parent >>= fun x' -> | |
452 returnM [CTimes (a, x')] | |
453 | CTimesJ (a, b) when b == node -> | |
454 dualM candidate_parent >>= fun x' -> | |
455 returnM [CTimesJ (a, x')] | |
456 | Uminus n when n == node -> | |
457 dualM candidate_parent >>= fun x' -> | |
458 returnM [makeUminus x'] | |
459 | _ -> returnM [] | |
460 | |
461 and dualExpressionM this_node = | |
462 mapM (termM this_node) | |
463 (match node_lookup this_node parent_table with | |
464 | Some a -> a | |
465 | None -> failwith "bug in dualExpressionM" | |
466 ) >>= fun l -> | |
467 returnM (makePlus (List.flatten l)) | |
468 | |
469 and dualM this_node = | |
470 memoizing lookupDualsM insertDualsM | |
471 (function | |
472 | Load v as x -> | |
473 if (Variable.is_constant v) then | |
474 returnM (Load v) | |
475 else | |
476 (dualExpressionM x >>= fun d -> | |
477 returnM (Store (v, d))) | |
478 | Store (v, x) -> returnM (Load v) | |
479 | x -> dualExpressionM x) | |
480 this_node | |
481 | |
482 in dualM | |
483 | |
484 let is_store = function | |
485 | Store _ -> true | |
486 | _ -> false | |
487 | |
488 let transpose dag = | |
489 let _ = Util.info "begin transpose" in | |
490 let (all_nodes, parent_table) = | |
491 visit [] Assoctable.empty Assoctable.empty dag in | |
492 let transposerM = make_transposer parent_table in | |
493 let mapTransposerM = mapM transposerM in | |
494 let duals = runM Assoctable.empty mapTransposerM all_nodes in | |
495 let roots = List.filter is_store duals in | |
496 let _ = Util.info "end transpose" in | |
497 roots | |
498 end | |
499 | |
500 | |
501 (************************************************************* | |
502 * Various dag statistics | |
503 *************************************************************) | |
504 module Stats : sig | |
505 type complexity | |
506 val complexity : Expr.expr list -> complexity | |
507 val same_complexity : complexity -> complexity -> bool | |
508 val leq_complexity : complexity -> complexity -> bool | |
509 val to_string : complexity -> string | |
510 end = struct | |
511 type complexity = int * int * int * int * int * int | |
512 let rec visit visited vtable = function | |
513 [] -> visited | |
514 | node :: rest -> | |
515 match node_lookup node vtable with | |
516 Some _ -> visit visited vtable rest | |
517 | None -> | |
518 let children = match node with | |
519 Store (v, n) -> [n] | |
520 | Plus l -> l | |
521 | Times (a, b) -> [a; b] | |
522 | Uminus x -> [x] | |
523 | _ -> [] | |
524 in visit (node :: visited) | |
525 (node_insert node () vtable) | |
526 (children @ rest) | |
527 | |
528 let complexity dag = | |
529 let rec loop (load, store, plus, times, uminus, num) = function | |
530 [] -> (load, store, plus, times, uminus, num) | |
531 | node :: rest -> | |
532 loop | |
533 (match node with | |
534 | Load _ -> (load + 1, store, plus, times, uminus, num) | |
535 | Store _ -> (load, store + 1, plus, times, uminus, num) | |
536 | Plus x -> (load, store, plus + (List.length x - 1), times, uminus, num) | |
537 | Times _ -> (load, store, plus, times + 1, uminus, num) | |
538 | Uminus _ -> (load, store, plus, times, uminus + 1, num) | |
539 | Num _ -> (load, store, plus, times, uminus, num + 1) | |
540 | CTimes _ -> (load, store, plus, times, uminus, num) | |
541 | CTimesJ _ -> (load, store, plus, times, uminus, num) | |
542 | NaN _ -> (load, store, plus, times, uminus, num)) | |
543 rest | |
544 in let (l, s, p, t, u, n) = | |
545 loop (0, 0, 0, 0, 0, 0) (visit [] Assoctable.empty dag) | |
546 in (l, s, p, t, u, n) | |
547 | |
548 let weight (l, s, p, t, u, n) = | |
549 l + s + 10 * p + 20 * t + u + n | |
550 | |
551 let same_complexity a b = weight a = weight b | |
552 let leq_complexity a b = weight a <= weight b | |
553 | |
554 let to_string (l, s, p, t, u, n) = | |
555 Printf.sprintf "ld=%d st=%d add=%d mul=%d uminus=%d num=%d\n" | |
556 l s p t u n | |
557 | |
558 end | |
559 | |
560 (* simplify the dag *) | |
561 let algsimp v = | |
562 let rec simplification_loop v = | |
563 let () = Util.info "simplification step" in | |
564 let complexity = Stats.complexity v in | |
565 let () = Util.info ("complexity = " ^ (Stats.to_string complexity)) in | |
566 let v = (AlgSimp.algsimp @@ Transpose.transpose @@ | |
567 AlgSimp.algsimp @@ Transpose.transpose) v in | |
568 let complexity' = Stats.complexity v in | |
569 let () = Util.info ("complexity = " ^ (Stats.to_string complexity')) in | |
570 if (Stats.leq_complexity complexity' complexity) then | |
571 let () = Util.info "end algsimp" in | |
572 v | |
573 else | |
574 simplification_loop v | |
575 | |
576 in | |
577 let () = Util.info "begin algsimp" in | |
578 let v = AlgSimp.algsimp v in | |
579 if !Magic.network_transposition then simplification_loop v else v | |
580 |