|
|
@ -231,8 +231,8 @@ let assert_monomial mono =
|
|
|
|
| Mul args ->
|
|
|
|
| Mul args ->
|
|
|
|
Qset.iter args ~f:(fun factor exponent ->
|
|
|
|
Qset.iter args ~f:(fun factor exponent ->
|
|
|
|
assert (Q.sign exponent > 0) ;
|
|
|
|
assert (Q.sign exponent > 0) ;
|
|
|
|
assert_indeterminate factor |> Fn.id )
|
|
|
|
assert_indeterminate factor |> Fun.id )
|
|
|
|
| _ -> assert_indeterminate mono |> Fn.id
|
|
|
|
| _ -> assert_indeterminate mono |> Fun.id
|
|
|
|
|
|
|
|
|
|
|
|
(* a polynomial term is a monomial multiplied by a non-zero coefficient
|
|
|
|
(* a polynomial term is a monomial multiplied by a non-zero coefficient
|
|
|
|
* c × ∏ᵢ xᵢ
|
|
|
|
* c × ∏ᵢ xᵢ
|
|
|
@ -246,8 +246,8 @@ let assert_poly_term mono coeff =
|
|
|
|
| None | Some (Integer _, _) -> assert false
|
|
|
|
| None | Some (Integer _, _) -> assert false
|
|
|
|
| Some (_, n) -> assert (Qset.length args > 1 || not (Q.equal Q.one n))
|
|
|
|
| Some (_, n) -> assert (Qset.length args > 1 || not (Q.equal Q.one n))
|
|
|
|
) ;
|
|
|
|
) ;
|
|
|
|
assert_monomial mono |> Fn.id
|
|
|
|
assert_monomial mono |> Fun.id
|
|
|
|
| _ -> assert_monomial mono |> Fn.id
|
|
|
|
| _ -> assert_monomial mono |> Fun.id
|
|
|
|
|
|
|
|
|
|
|
|
(* a polynomial is a linear combination of monomials, e.g.
|
|
|
|
(* a polynomial is a linear combination of monomials, e.g.
|
|
|
|
* ∑ᵢ cᵢ × ∏ⱼ xᵢⱼ
|
|
|
|
* ∑ᵢ cᵢ × ∏ⱼ xᵢⱼ
|
|
|
@ -261,7 +261,7 @@ let assert_polynomial poly =
|
|
|
|
| None | Some (Integer _, _) -> assert false
|
|
|
|
| None | Some (Integer _, _) -> assert false
|
|
|
|
| Some (_, k) -> assert (Qset.length args > 1 || not (Q.equal Q.one k))
|
|
|
|
| Some (_, k) -> assert (Qset.length args > 1 || not (Q.equal Q.one k))
|
|
|
|
) ;
|
|
|
|
) ;
|
|
|
|
Qset.iter args ~f:(fun m c -> assert_poly_term m c |> Fn.id)
|
|
|
|
Qset.iter args ~f:(fun m c -> assert_poly_term m c |> Fun.id)
|
|
|
|
| _ -> assert false
|
|
|
|
| _ -> assert false
|
|
|
|
|
|
|
|
|
|
|
|
(* aggregate args of Extract and Concat must be aggregate terms, in
|
|
|
|
(* aggregate args of Extract and Concat must be aggregate terms, in
|
|
|
@ -278,8 +278,8 @@ let invariant e =
|
|
|
|
Invariant.invariant [%here] e [%sexp_of: t]
|
|
|
|
Invariant.invariant [%here] e [%sexp_of: t]
|
|
|
|
@@ fun () ->
|
|
|
|
@@ fun () ->
|
|
|
|
match e with
|
|
|
|
match e with
|
|
|
|
| Add _ -> assert_polynomial e |> Fn.id
|
|
|
|
| Add _ -> assert_polynomial e |> Fun.id
|
|
|
|
| Mul _ -> assert_monomial e |> Fn.id
|
|
|
|
| Mul _ -> assert_monomial e |> Fun.id
|
|
|
|
| Ap2 (Memory, _, _) | Ap3 (Extract, _, _, _) | ApN (Concat, _) ->
|
|
|
|
| Ap2 (Memory, _, _) | Ap3 (Extract, _, _, _) | ApN (Concat, _) ->
|
|
|
|
assert_aggregate e
|
|
|
|
assert_aggregate e
|
|
|
|
| ApN (Record, elts) | RecN (Record, elts) ->
|
|
|
|
| ApN (Record, elts) | RecN (Record, elts) ->
|
|
|
@ -788,10 +788,10 @@ let simp_uno x y = Ap2 (Uno, x, y)
|
|
|
|
|
|
|
|
|
|
|
|
let rec simp_eq x y =
|
|
|
|
let rec simp_eq x y =
|
|
|
|
match
|
|
|
|
match
|
|
|
|
match Ordering.of_int (compare x y) with
|
|
|
|
match Int.sign (compare x y) with
|
|
|
|
| Equal -> None
|
|
|
|
| Zero -> None
|
|
|
|
| Less -> Some (x, y)
|
|
|
|
| Neg -> Some (x, y)
|
|
|
|
| Greater -> Some (y, x)
|
|
|
|
| Pos -> Some (y, x)
|
|
|
|
with
|
|
|
|
with
|
|
|
|
(* e = e ==> true *)
|
|
|
|
(* e = e ==> true *)
|
|
|
|
| None -> bool true
|
|
|
|
| None -> bool true
|
|
|
@ -934,8 +934,7 @@ let simp_update idx rcd elt = Ap2 (Update idx, rcd, elt)
|
|
|
|
let rec_app key =
|
|
|
|
let rec_app key =
|
|
|
|
let memo_id = Hashtbl.create key in
|
|
|
|
let memo_id = Hashtbl.create key in
|
|
|
|
let dummy = null in
|
|
|
|
let dummy = null in
|
|
|
|
Staged.stage
|
|
|
|
fun ~id op elt_thks ->
|
|
|
|
@@ fun ~id op elt_thks ->
|
|
|
|
|
|
|
|
match Hashtbl.find memo_id id with
|
|
|
|
match Hashtbl.find memo_id id with
|
|
|
|
| None ->
|
|
|
|
| None ->
|
|
|
|
(* Add placeholder to prevent computing [elts] in calls to [rec_app]
|
|
|
|
(* Add placeholder to prevent computing [elts] in calls to [rec_app]
|
|
|
@ -946,11 +945,12 @@ let rec_app key =
|
|
|
|
Vector.iteri elt_thks ~f:(fun i (lazy elt) -> elta.(i) <- elt) ;
|
|
|
|
Vector.iteri elt_thks ~f:(fun i (lazy elt) -> elta.(i) <- elt) ;
|
|
|
|
RecN (op, elts) |> check invariant
|
|
|
|
RecN (op, elts) |> check invariant
|
|
|
|
| Some elts ->
|
|
|
|
| Some elts ->
|
|
|
|
(* Do not check invariant as invariant will be checked above after the
|
|
|
|
(* Do not check invariant as invariant will be checked above after
|
|
|
|
thunks are forced, before which invariant-checking may spuriously
|
|
|
|
the thunks are forced, before which invariant-checking may
|
|
|
|
fail. Note that it is important that the value constructed here
|
|
|
|
spuriously fail. Note that it is important that the value
|
|
|
|
shares the array in the memo table, so that the update after
|
|
|
|
constructed here shares the array in the memo table, so that the
|
|
|
|
forcing the recursive thunks also updates this value. *)
|
|
|
|
update after forcing the recursive thunks also updates this
|
|
|
|
|
|
|
|
value. *)
|
|
|
|
RecN (op, elts)
|
|
|
|
RecN (op, elts)
|
|
|
|
|
|
|
|
|
|
|
|
(* dispatching for normalization and invariant checking *)
|
|
|
|
(* dispatching for normalization and invariant checking *)
|
|
|
|