You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

34 lines
1.1 KiB

(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
(** Arithmetic terms *)
include module type of Arithmetic_intf
[sledge] Rework term and arithmetic definitions to avoid recursive modules Summary: Terms include Arithmetic terms, which are polynomials over terms themselves. Monomials are represented as maps from terms (multiplicative factors) to integers (their powers). Polynomials are represented as maps from monomials (indeterminates) to rationals (coefficients). In particular, terms are represented using maps whose keys are terms themselves. This is currently implemented using recursive modules. This diff uses the Comparer-based interface of Maps to express this cycle as recursive *types* rather than recursive *modules*, see the very beginning of trm.ml. The rest of the changes are driven by the need to expose the Arithmetic.t type at toplevel, outside the functor that defines the arithmetic operations, and changes to stage the definition of term and polynomial operations to remove unnecessary recursion. One might hope that these changes are just moving code around, but due to how recursive modules are implemented, this refactoring is motivated by performance profiling. In every cycle between recursive modules, at least one of the modules must be "safe". A "safe" module is one where all exposed values have function type. This allows the compiler to initialize that module with functions that immediately raise an exception, define the other modules using it, and then tie the recursive knot by backpatching the safe module with the actual functions at the end. This implementation works, but has the consequence that the compiler must treat calls to functions of safe recursive modules as indirect calls to unknown functions. This means that they are not inlined or even called by symbol, and instead calling them involves spilling registers if needed, loading their address from memory, calling them by address, and restoring any spilled registers. For operations like Trm.compare that are a handful of instructions on the hot path, this is a significant difference. Since terms are the keys of maps and sets in the core of the first-order equality solver, those map operations are very very hot. Reviewed By: jvillard Differential Revision: D26250533 fbshipit-source-id: f79334c68
4 years ago
(** Arithmetic terms, e.g. polynomials, polymorphic in the type of
indeterminates. *)
type ('trm, 'cmp) t [@@deriving compare, equal, sexp]
(** Functor that, given a totally ordered type of indeterminate terms,
builds an implementation of the embedding-independent arithmetic
operations, and a functor that, given an embedding of arithmetic terms
into indeterminate terms, builds an implementation of the arithmetic
operations. *)
module Make (Ord : sig
type t [@@deriving equal, sexp]
include Comparer.S with type t := t
end) : sig
include S0 with type t = (Ord.t, Ord.compare) t with type trm := Ord.t
module Embed
(Var : Var_intf.S)
(Trm : TRM with type t = Ord.t with type var := Var.t)
(_ : EMBEDDING with type trm := Trm.t and type t := t) :
S with type trm := Trm.t with type t = t
end