diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,8 +1,194 @@
 * Hackage: <http://hackage.haskell.org/package/sbv>
 * GitHub:  <http://leventerkok.github.com/sbv/>
 
-* Latest Hackage released version: 8.0, 2019-01-14
+* Latest Hackage released version: 8.1, 2019-03-09
 
+### Version 8.1, 2019-03-09
+
+  * Added support for `SEither` and `SMaybe` types: symbolic sums and symbolic
+    optional values. These can be accessed by importing `Data.SBV.Either` and
+    `Data.SBV.Maybe` respectively. They translate to SMTLib's data-type syntax,
+    and thus require a solver capable of handling datatypes. (Currently z3 and
+    cvc4 are the only solvers that do.) All the typical introduction and
+    elimination functions are provided, and these types integrate with all
+    other symbolic types. (So you can have a list of SMaybe of SEither
+    values, or at any nesting level.) Thanks to Joel Burget for the initial
+    implementation of this idea and his contributions.
+
+  * Added support for symbolic sets. The API closely follows that of `Data.Set`
+    of Haskell, with some major differences: Symbolic sets can be co-finite.
+    (That is, we can represent not only finite sets, but also sets whose complements
+    are finite.) The distinction shows up in the `complement` operation, which
+    is not supported in Haskell. All SBV sets can be complemented. On the flip
+    side, SBV sets do not support a size operation (as they can be infinite),
+    nor they can be converted to lists. See 'Data.SBV.Set' for the API documentation
+    and "Documentation/SBV/Examples/Misc/SetAlgebra.hs" for an example that proves
+    many familiar set properties.
+
+  * SBV models now contain values for uninterpreted functions. This was a long
+    requested feature, but there was no previous support since SMTLib does not
+    have a standard way of querying such values. We now support this for z3 and
+    cvc4: Note that SBV tries its best to interpret the output from these
+    solvers, but it may give up if the response is too complicated (or something
+    I haven't seen before!) due to non-standard format. Barring these details,
+    the calls to `sat` now include function models, and you can also get them
+    via `getFunction` in a query.
+
+    For an example use case demonstrating how to use UF-models to synthesize a
+    simple multiplier, see "Documentation/SBV/Examples/Uninterpreted/Multiply.hs".
+
+  * SBV now comes with a model validator. In a 'sat', 'prove', or 'allSat' call,
+    you can pass the configuration parameter 'z3{validateModel = True}' (or whichever
+    solver you're using), and z3 will attempt to validate the returned model
+    from the solver. Note that validation only works if there are no uninterpreted
+    kinds of functions, and also in quantifier-free problems only. Please report
+    your experiences, as there's room for improvement in validation, always!
+
+  * [BACKWARDS COMPATIBILITY] The `allSat` function is similarly modified to
+    return uninterpreted-function models. There are a few technical restrictions,
+    however: Only the values of uninterpreted functions without any uninterpreted
+    arguments will participate in `allSat` computation. (For instance,
+    `uninterpret "f" :: SInteger -> SInteger` is OK, but
+    `uninterpret "f" :: MyType -> SInteger` is not, where `MyType` itself
+    is uninterpreted.) The reason for this is again there is no SMTLib way of
+    reflecting uninterpreted model values back into the solver. This restriction
+    should not cause much trouble in practice, but do get in touch if it is a
+    use-case for you.
+
+  * Added configuration option `allSatPrintAlong`. If set to True, calls to
+    allSat will print their models as they are found. The default is False.
+
+  * Added configuration parameter `satTrackUFs` (defaulting to True) to control
+    if SBV should try to extract models for uninterpreted functions. In theory,
+    this should always be True, but for most practical problems we typically
+    don't care about the function values itself but that it exists. Set to 'False'
+    if this is the case for your problem. Note that this setting is also respected
+    in 'allSat' calls.
+
+  * Added function `registerUISMTFunction`, which can be used to directly register uninterpreted
+    functions. This is typically not necessary as uses of UI-functions do register them
+    automatically, but it can come in handy in certain scenarios where there are no
+    constraints on a UI-function other than its existence.
+
+  * Added `Data.SBV.Tools.WeakestPreconditions` module, which provides a toy imperative
+    language and an engine for checking partial and total correctness of imperative programs.
+    It uses Dijkstra's weakest preconditions methodology to establish correctness claims.
+    Loop invariants are required and must be supplied by the user. For total correctness,
+    user must also provide termination measure functions. However, if desired, these can
+    be skipped (by passing 'Nothing'), in which case partial correctness will be proven.
+    Checking input parameters for no-change is supported via stability checks. For example
+    use cases, see the `Documentation.SBV.Examples.WeakestPreconditions` directory.
+
+  * Added functions `elem`/`notElem` to `Data.SBV.List`.
+
+  * Added `snoc` (appending a single element at the end) to `Data.SBV.List` and `Data.SBV.String`.
+
+  * Rework the 'Queriable' class to allow projection/embedding pairs. Also
+    added a new 'Fresh' class, which is more usable in simpler scenarios
+    where the default projection/embedding definitions are suitable.
+
+  * Added strong-equality (.===) and inequality (./==) to the 'EqSymbolic' class. This
+    method is equivalent to the usual (.==) and (./=) for all types except 'SFloat' and
+    'SDouble'. For the floating types, it is object equality, that is 'NaN .=== Nan'
+    and '0 ./== -0'. Use the regular equality for float/double's as they follow the
+    IEEE754 rules, but occasionally we need to express object equality in a polymorphic
+    way. Essentially this method is the polymorphic equaivalent of 'fpIsEqualObject'
+    except it works on all types.
+
+  * Removed the redundant 'SDivisible' constraint on rotate-left and rotate-right operations.
+
+  * Added unnamed equivalents of 'sBool', 'sWord8' etc; with a following underscore, i.e.,
+    'sBool_', 'sWord8_'. The new functions are supported for all base types, chars,
+    strings, lists, and tuples.
+
+  * SBV now supports implicit constraints in the query mode, which were previously only
+    available before user queries started.
+
+  * Fixed a bug where hash-consing might reuse an expression even though the request might
+    have been made at a different type. This is a rare case in SBV to happen due to types,
+    but it was possible to exploit it in the Dynamic interface. Thanks to Brian Huffman
+    for reporting and diagnosing the issue.
+
+  * Fixed a bug where SBV was reporting incorrect "elapsed" time values, which are
+    printed when the 'timing' configuration parameter is specified.
+
+  * Documentation: Jan Path kindly fixed module headers of all the files to produce
+    much better looking Haddock documents. Thanks Jan!
+
+  * Added barrel-rotations (sBarrelRotateLeft-Right, svBarrelRotateLeft-Right) which
+    can produce better code for verification by bit-blasting the rotation amount.
+    It accepts bit-vectors as arguments and an unsigned rotation quantity to keep
+    things simple.
+
+  * Added new configuration option 'allowQueryQuantifers', default is set to False.
+    SBV normally doesn't allow quantifiers in a query context, because there are
+    issues surrounding 'getValue'. However, Joel Burget pointed out this check
+    is too strict for certain scenarios. So, as an escape hatch, you can define
+    'allowQueryQuantifers' to be 'True' and SBV will bypass this check. Of course,
+    if you do this, then you are on your own regarding calls to `getValue` with
+    quantified parameters! See http://github.com/LeventErkok/sbv/issues/459
+    for details.
+
+  * [BACKWARDS COMPATIBILITY] Renamed the class `IEEEFloatConvertable` to
+    `IEEEFloatConvertible`. (Typo in name!) Matt Peddie pointed out issues
+    regarding conversion of out-of-bounds float and double values to integral
+    types. Unfortunately SMTLib does not support these conversions, and we
+    had issues in getting Haskell, SMTLib, and C to agree. Summary: These conversions
+    are only guaranteed to work if they are done on numbers that lie within the
+    representable range of the target type. Thanks to Matt Peddie for pointing out
+    the out-of-bounds problem, his help in figuring out the issues.
+
+  * [BACKWARDS COMPATIBILITY] The 'AllSat' result now tracks if search has stopped
+    because the solver returned 'Unknown'. Previously this information was not
+    displayed.
+
+  * [BACKWARDS COMPATIBILITY, Internal] Several constraints on internal
+    classes (such as SymVal, EqSymbolic, OrdSymbolic) were reworked to
+    reflect the dependencies better. Strictly speaking this is a backwards
+    compatibility breaking change, but I doubt it'll impact any user
+    code; though you might have to add some extra constraints if you were
+    writing sufficiently polymorphic SBV code. Yell if you find otherwise!
+
+  * [BACKWARDS COMPATIBILITY] SBV now allows user-given names to be duplicated.
+    It will implicitly add a suffix to them to distinguish without complaining. (In
+    previous versions, we would error out.) The reason for this change is that
+    sometimes it's nice to be able to simply give a prefix for a class of names
+    and not worry about the actual name itself. (Note that this will cause issues
+    if you use model-extraction-via-maps method if we ever make a name unique
+    and store it under a different name, but that's hardly ever used feature and
+    arguably the right thing to do anyway.) Thanks to Joel Burget for suggesting
+    the idea.
+
+  * [BACKWARDS COMPATIBILITY, Internal] SBV is now more strict in how user-queries
+    are used, performing certain extra-checks that were not done before. (For instance,
+    previously it was possible to mix prove-sat with a query call, which should
+    not have been allowed.) If you have any code that breaks for this reason, you
+    probably should've written it in some other way to start with. Please get
+    in touch if that is the case.
+
+  * [BACKWARDS COMPATIBILITY] You need at least GHC 8.4.1 to compile SBV.
+    If you're stuck with an older version, let me know and we'll see if
+    we can create a custom version for you; though I'd much rather avoid this
+    if at all possible.
+
+  * SBV now supports optimization of goals of SDouble and SFloat types. This is
+    done using the lexicographic ordering on floats, and adds on the additional
+    constraint that the resulting float is not a NaN. If you use this feature,
+    then your float value will be minimized as the corresponding 32 (or 64 for
+    doubles) bit word. Note that this methods supports infinities properly, and
+    does not distinguish between -0 and +0.
+    
+  * Optimization routines have been generalized to work over arbitrary metric-spaces,
+    with user-definable mappings. The simplest instance we have added is optimization
+    over booleans, by the obvious numeric mapping. Tuples are also supported with
+    the usual lexicographic ordering. In addition, SBV can now optimize over
+    user-defined enumerations. See "Documentation.SBV.Examples.Optimization.Enumerate" for
+    an example.
+
+  * Improved the internal representation of constraints to address performance
+    issues See http://github.com/LeventErkok/sbv/issues/460 for details. Thanks to
+    Thanks Jeffrey Young for reporting.
+
 ### Version 8.0, 2019-01-14
 
   * This is a major release of SBV, with several BACKWARDS COMPATIBILITY breaking
@@ -32,12 +218,12 @@
     8-tuples), and allows mixing and matching of lists and tuples arbitrarily
     as symbolic values. For instance `SBV [(Integer, String)]` is a valid type as
     is `SBV [(Integer, [(Char, (Float, String))])]`, with each component symbolically
-    represented. There are new type synonyms for `STupleN` for `N` between 2 to 8,
-    along with `untuple` destructor, and field accessors similar to lens: For instance
-    `p^._4` would project the 4th element of a tuple that has at least 4 fields.
-    The mixing and matching of field types and nesting allows for very rich
-    symbolic value representations. See `Documentation.SBV.Examples.Misc.Tuple` for
-    an example.
+    represented. Along with `STuple` for regular 2-tuples, there are new types
+    for `STupleN` for `N` between 2 to 8, along with `untuple` destructor, and field
+    accessors similar to lens: For instance `p^._4` would project the 4th element of
+    a tuple that has at least 4 fields. The mixing and matching of field types and
+    nesting allows for very rich symbolic value representations. See
+    `Documentation.SBV.Examples.Misc.Tuple` for an example.
 
   * [BACKWARDS COMPATIBILITY] The `Boolean` class is removed, which used to abstract
     over logical connectives. Previously, this class handled 'SBool' and 'Bool', but
@@ -181,7 +367,7 @@
 ### Version 7.10, 2018-07-20
   * [BACKWARDS COMPATIBILITY] '==' and '/=' now always throw an error instead of
     only throwing an error for non-concrete values.
-    https://github.com/LeventErkok/sbv/issues/301
+    http://github.com/LeventErkok/sbv/issues/301
 
   * [BACKWARDS COMPATIBILITY] Array declarations are reworked to take
     an initial value. The call 'newArray' now accepts an optional default
@@ -328,7 +514,7 @@
     handles this corner case properly, by using tracker assertions
     to keep track of what array values must be restored at each pop.
     Thanks to Martin Brain on the SMTLib mailing list for the
-    suggestion. (See https://github.com/LeventErkok/sbv/issues/374
+    suggestion. (See http://github.com/LeventErkok/sbv/issues/374
     for details.)
 
   * Fix corner case in ite branch equality with float/double arguments,
@@ -432,7 +618,7 @@
     backend solver is no longer alive: You should either just throw it,
     or perform proper clean-up on your user code as required to set up
     a new context. The provided show instance formats the exception nicely
-    for display purposes. See https://github.com/LeventErkok/sbv/issues/335
+    for display purposes. See http://github.com/LeventErkok/sbv/issues/335
     for details and thanks to Brian Huffman for reporting.
 
   * SIntegral class now has Integral as a super-class, which ensures the
@@ -493,7 +679,7 @@
   * Fix optimization routines when applied to signed-bitvector goals. Thanks
     to Anders Kaseorg for reporting. Since SMT-Lib does not distinguish between
     signed and unsigned bit-vectors, we have to be careful when expressing goals
-    that are over signed values. See https://github.com/LeventErkok/sbv/issues/333
+    that are over signed values. See http://github.com/LeventErkok/sbv/issues/333
     for details.
 
 ### Version 7.3, 2017-09-06
@@ -748,7 +934,7 @@
     capability optimize objectives, and solve MaxSAT problems; by appropriately
     employing the corresponding capabilities in z3. A good review of these features
     as implemented by Z3, and thus what is available in SBV is given in this
-    paper: http://www.easychair.org/publications/download/Z_-_Maximal_Satisfaction_with_Z3
+    paper: http://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/nbjorner-scss2014.pdf
 
   * SBV now allows for  real or integral valued metrics. Goals can be lexicographically
     (default), independently, or pareto-front optimized. Currently, only the z3 backend
@@ -919,7 +1105,7 @@
     perspective. This comes handy in doing an `allSat` calls where
     there might be witness variables that we do not care the uniqueness
     for. See `Data/SBV/Examples/Misc/Auxiliary.hs` for an example, and
-    the discussion in https://github.com/LeventErkok/sbv/issues/208 for
+    the discussion in http://github.com/LeventErkok/sbv/issues/208 for
     motivation.
 
   * Yices interface: If Reals are used, then pick the logic QF_UFLRA, instead
@@ -1394,7 +1580,7 @@
 
 ### Version 3.1, 2014-07-12
 
- NB: GHC 7.8.1 and 7.8.2 has a serious bug <https://ghc.haskell.org/trac/ghc/ticket/9078>
+ NB: GHC 7.8.1 and 7.8.2 has a serious bug <http://ghc.haskell.org/trac/ghc/ticket/9078>
      that causes SBV to crash under heavy/repeated calls. The bug is addressed
      in GHC 7.8.3; so upgrading to GHC 7.8.3 is essential for using SBV!
 
diff --git a/Data/SBV.hs b/Data/SBV.hs
--- a/Data/SBV.hs
+++ b/Data/SBV.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -19,7 +19,7 @@
 --
 -- >>> prove $ \x -> x `shiftL` 2 .== 2 * (x :: SWord8)
 -- Falsifiable. Counter-example:
---   s0 = 64 :: Word8
+--   s0 = 32 :: Word8
 --
 -- The function 'prove' has the following type:
 --
@@ -52,6 +52,14 @@
 --
 --   * 'SList': Symbolic lists (which can be nested)
 --
+--   * 'STuple', 'STuple2', 'STuple3', .., 'STuple8' : Symbolic tuples (upto 8-tuples, can be nested)
+--
+--   * 'SEither': Symbolic sums
+--
+--   * 'SMaybe': Symbolic optional values
+--
+--   * 'SSet': Symbolic sets
+--
 --   * 'SArray', 'SFunArray': Flat arrays of symbolic values.
 --
 --   * Symbolic polynomials over GF(2^n), polynomial arithmetic, and CRCs.
@@ -61,6 +69,10 @@
 --
 --   * Uninterpreted sorts, and proofs over such sorts, potentially with axioms.
 --
+--   * Model validation: SBV can validate models returned by solvers, which allows
+--     for protection against bugs in SMT solvers and SBV itself. (See the 'validateModel'
+--     parameter.)
+--
 -- The user can construct ordinary Haskell programs using these types, which behave
 -- very similar to their concrete counterparts. In particular these types belong to the
 -- standard classes 'Num', 'Bits', custom versions of 'Eq' ('EqSymbolic')
@@ -145,18 +157,48 @@
   , SList
   -- ** Tuples
   -- $tuples
-  , STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
+  , STuple, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
+  -- ** Sum types
+  , SMaybe, SEither
+  -- ** Sets
+  , RCSet(..), SSet
   -- * Arrays of symbolic values
   , SymArray(readArray, writeArray, mergeArrays), newArray_, newArray, SArray, SFunArray
 
   -- * Creating symbolic values
   -- ** Single value
   -- $createSym
-  , sBool, sWord8, sWord16, sWord32, sWord64, sInt8, sInt16, sInt32, sInt64, sInteger, sReal, sFloat, sDouble, sChar, sString, sList, sTuple
+  , sBool, sBool_
+  , sWord8, sWord8_, sWord16, sWord16_, sWord32, sWord32_, sWord64, sWord64_
+  , sInt8,  sInt8_,  sInt16,  sInt16_,  sInt32,  sInt32_,  sInt64,  sInt64_
+  , sInteger, sInteger_
+  , sReal, sReal_
+  , sFloat, sFloat_
+  , sDouble, sDouble_
+  , sChar, sChar_
+  , sString, sString_
+  , sList, sList_
+  , sTuple, sTuple_
+  , sEither, sEither_
+  , sMaybe, sMaybe_
+  , sSet, sSet_
 
   -- ** List of values
   -- $createSyms
-  , sBools, sWord8s, sWord16s, sWord32s, sWord64s, sInt8s, sInt16s, sInt32s, sInt64s, sIntegers, sReals, sFloats, sDoubles, sChars, sStrings, sLists, sTuples
+  , sBools
+  , sWord8s, sWord16s, sWord32s, sWord64s
+  , sInt8s,  sInt16s,  sInt32s,  sInt64s
+  , sIntegers
+  , sReals
+  , sFloats
+  , sDoubles
+  , sChars
+  , sStrings
+  , sLists
+  , sTuples
+  , sEithers
+  , sMaybes
+  , sSets
 
   -- * Symbolic Equality and Comparisons
   , EqSymbolic(..), OrdSymbolic(..), Equality(..)
@@ -172,7 +214,7 @@
   , sFromIntegral
   -- ** Shifts and rotates
   -- $shiftRotate
-  , sShiftLeft, sShiftRight, sRotateLeft, sRotateRight, sSignedShiftArithRight
+  , sShiftLeft, sShiftRight, sRotateLeft, sBarrelRotateLeft, sRotateRight, sBarrelRotateRight, sSignedShiftArithRight
   -- ** Finite bit-vector operations
   , SFiniteBits(..)
   -- ** Splitting, joining, and extending
@@ -184,7 +226,7 @@
   -- ** Rounding modes
   , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero, sRNE, sRNA, sRTP, sRTN, sRTZ
   -- ** Conversion to/from floats
-  , IEEEFloatConvertable(..)
+  , IEEEFloatConvertible(..)
   -- ** Bit-pattern conversions
   , sFloatAsSWord32, sWord32AsSFloat, sDoubleAsSWord64, sWord64AsSDouble, blastSFloat, blastSDouble
 
@@ -240,9 +282,9 @@
   -- ** Multiple optimization goals
   -- $multiOpt
   , OptimizeStyle(..)
-  -- ** Objectives
+  -- ** Objectives and Metrics
   , Objective(..)
-  , Metric, minimize, maximize
+  , Metric(..), minimize, maximize
   -- ** Soft assertions
   -- $softAssertions
   , assertWithPenalty , Penalty(..)
@@ -303,14 +345,15 @@
                                         newArray, newArray_)
 import Data.SBV.Core.Model      hiding (assertWithPenalty, minimize, maximize,
                                         forall, forall_, exists, exists_,
-                                        solve, sBool, sBools, sChar, sChars,
-                                        sDouble, sDoubles, sFloat, sFloats,
-                                        sInt8, sInt8s, sInt16, sInt16s, sInt32, sInt32s,
-                                        sInt64, sInt64s, sInteger, sIntegers,
-                                        sList, sLists, sTuple, sTuples,
-                                        sReal, sReals, sString, sStrings,
-                                        sWord8, sWord8s, sWord16, sWord16s,
-                                        sWord32, sWord32s, sWord64, sWord64s)
+                                        solve, sBool, sBool_, sBools, sChar, sChar_, sChars,
+                                        sDouble, sDouble_, sDoubles, sFloat, sFloat_, sFloats,
+                                        sInt8, sInt8_, sInt8s, sInt16, sInt16_, sInt16s, sInt32, sInt32_, sInt32s,
+                                        sInt64, sInt64_, sInt64s, sInteger, sInteger_, sIntegers,
+                                        sList, sList_, sLists, sTuple, sTuple_, sTuples,
+                                        sReal, sReal_, sReals, sString, sString_, sStrings,
+                                        sWord8, sWord8_, sWord8s, sWord16, sWord16_, sWord16s,
+                                        sWord32, sWord32_, sWord32s, sWord64, sWord64_, sWord64s,
+                                        sMaybe, sMaybe_, sMaybes, sEither, sEither_, sEithers, sSet, sSet_, sSets)
 import Data.SBV.Core.Floating
 import Data.SBV.Core.Splittable
 import Data.SBV.Core.Symbolic   (MonadSymbolic(..), SymbolicT)
@@ -418,8 +461,8 @@
 
 >>> safe (sub :: SInt8 -> SInt8 -> SInt8)
 [sub: x >= y must hold!: Violated. Model:
-  s0 = 0 :: Int8
-  s1 = 1 :: Int8]
+  s0 = 30 :: Int8
+  s1 = 32 :: Int8]
 
 What happens if we make sure to arrange for this invariant? Consider this version:
 
@@ -582,7 +625,8 @@
 
 {- $createSym
 These functions simplify declaring symbolic variables of various types. Strictly speaking, they are just synonyms
-for 'free' (specialized at the given type), but they might be easier to use.
+for 'free' (specialized at the given type), but they might be easier to use. We provide both the named and anonymous
+versions, latter with the underscore suffix.
 -}
 
 {- $createSyms
diff --git a/Data/SBV/Char.hs b/Data/SBV/Char.hs
--- a/Data/SBV/Char.hs
+++ b/Data/SBV/Char.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Char
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/Client.hs b/Data/SBV/Client.hs
--- a/Data/SBV/Client.hs
+++ b/Data/SBV/Client.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Client
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/Client/BaseIO.hs b/Data/SBV/Client/BaseIO.hs
--- a/Data/SBV/Client/BaseIO.hs
+++ b/Data/SBV/Client/BaseIO.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Client.BaseIO
--- Author    : Brian Schroeder, Levent Erkok
+-- Copyright : (c) Brian Schroeder
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -18,8 +19,8 @@
                                 SymVal, SBool, SBV, SChar, SDouble, SFloat,
                                 SInt8, SInt16, SInt32, SInt64, SInteger, SList,
                                 SReal, SString, SV, SWord8, SWord16, SWord32,
-                                SWord64)
-import Data.SBV.Core.Model     (Metric)
+                                SWord64, SEither, SMaybe, SSet)
+import Data.SBV.Core.Model     (Metric(..))
 import Data.SBV.Core.Symbolic  (Objective, OptimizeStyle, Quantifier, Result,
                                 Symbolic, SBVRunMode, SMTConfig, SVal)
 import Data.SBV.Control.Types  (SMTOption)
@@ -314,173 +315,251 @@
 genMkSymVar :: Kind -> Maybe Quantifier -> Maybe String -> Symbolic (SBV a)
 genMkSymVar = Trans.genMkSymVar
 
--- | Declare an 'SBool'
+-- | Declare a named 'SBool'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sBool'
 sBool :: String -> Symbolic SBool
 sBool = Trans.sBool
 
+-- | Declare an unnamed 'SBool'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sBool_'
+sBool_ :: Symbolic SBool
+sBool_ = Trans.sBool_
+
 -- | Declare a list of 'SBool's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sBools'
 sBools :: [String] -> Symbolic [SBool]
 sBools = Trans.sBools
 
--- | Declare an 'SWord8'
+-- | Declare a named 'SWord8'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord8'
 sWord8 :: String -> Symbolic SWord8
 sWord8 = Trans.sWord8
 
+-- | Declare an unnamed 'SWord8'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord8_'
+sWord8_ :: Symbolic SWord8
+sWord8_ = Trans.sWord8_
+
 -- | Declare a list of 'SWord8's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord8s'
 sWord8s :: [String] -> Symbolic [SWord8]
 sWord8s = Trans.sWord8s
 
--- | Declare an 'SWord16'
+-- | Declare a named 'SWord16'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord16'
 sWord16 :: String -> Symbolic SWord16
 sWord16 = Trans.sWord16
 
+-- | Declare an unnamed 'SWord16'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord16_'
+sWord16_ :: Symbolic SWord16
+sWord16_ = Trans.sWord16_
+
 -- | Declare a list of 'SWord16's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord16s'
 sWord16s :: [String] -> Symbolic [SWord16]
 sWord16s = Trans.sWord16s
 
--- | Declare an 'SWord32'
+-- | Declare a named 'SWord32'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord32'
 sWord32 :: String -> Symbolic SWord32
 sWord32 = Trans.sWord32
 
+-- | Declare an unamed 'SWord32'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord32_'
+sWord32_ :: Symbolic SWord32
+sWord32_ = Trans.sWord32_
+
 -- | Declare a list of 'SWord32's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord32s'
 sWord32s :: [String] -> Symbolic [SWord32]
 sWord32s = Trans.sWord32s
 
--- | Declare an 'SWord64'
+-- | Declare a named 'SWord64'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord64'
 sWord64 :: String -> Symbolic SWord64
 sWord64 = Trans.sWord64
 
+-- | Declare an unnamed 'SWord64'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord64_'
+sWord64_ :: Symbolic SWord64
+sWord64_ = Trans.sWord64_
+
 -- | Declare a list of 'SWord64's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sWord64s'
 sWord64s :: [String] -> Symbolic [SWord64]
 sWord64s = Trans.sWord64s
 
--- | Declare an 'SInt8'
+-- | Declare a named 'SInt8'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt8'
 sInt8 :: String -> Symbolic SInt8
 sInt8 = Trans.sInt8
 
+-- | Declare an unnamed 'SInt8'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt8_'
+sInt8_ :: Symbolic SInt8
+sInt8_ = Trans.sInt8_
+
 -- | Declare a list of 'SInt8's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt8s'
 sInt8s :: [String] -> Symbolic [SInt8]
 sInt8s = Trans.sInt8s
 
--- | Declare an 'SInt16'
+-- | Declare a named 'SInt16'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt16'
 sInt16 :: String -> Symbolic SInt16
 sInt16 = Trans.sInt16
 
+-- | Declare an unnamed 'SInt16'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt16_'
+sInt16_ :: Symbolic SInt16
+sInt16_ = Trans.sInt16_
+
 -- | Declare a list of 'SInt16's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt16s'
 sInt16s :: [String] -> Symbolic [SInt16]
 sInt16s = Trans.sInt16s
 
--- | Declare an 'SInt32'
+-- | Declare a named 'SInt32'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt32'
 sInt32 :: String -> Symbolic SInt32
 sInt32 = Trans.sInt32
 
+-- | Declare an unnamed 'SInt32'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt32_'
+sInt32_ :: Symbolic SInt32
+sInt32_ = Trans.sInt32_
+
 -- | Declare a list of 'SInt32's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt32s'
 sInt32s :: [String] -> Symbolic [SInt32]
 sInt32s = Trans.sInt32s
 
--- | Declare an 'SInt64'
+-- | Declare a named 'SInt64'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt64'
 sInt64 :: String -> Symbolic SInt64
 sInt64 = Trans.sInt64
 
+-- | Declare an unnamed 'SInt64'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt64_'
+sInt64_ :: Symbolic SInt64
+sInt64_ = Trans.sInt64_
+
 -- | Declare a list of 'SInt64's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInt64s'
 sInt64s :: [String] -> Symbolic [SInt64]
 sInt64s = Trans.sInt64s
 
--- | Declare an 'SInteger'
+-- | Declare a named 'SInteger'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInteger'
 sInteger :: String -> Symbolic SInteger
 sInteger = Trans.sInteger
 
+-- | Declare an unnamed 'SInteger'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sInteger_'
+sInteger_ :: Symbolic SInteger
+sInteger_ = Trans.sInteger_
+
 -- | Declare a list of 'SInteger's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sIntegers'
 sIntegers :: [String] -> Symbolic [SInteger]
 sIntegers = Trans.sIntegers
 
--- | Declare an 'SReal'
+-- | Declare a named 'SReal'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sReal'
 sReal :: String -> Symbolic SReal
 sReal = Trans.sReal
 
+-- | Declare an unnamed 'SReal'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sReal_'
+sReal_ :: Symbolic SReal
+sReal_ = Trans.sReal_
+
 -- | Declare a list of 'SReal's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sReals'
 sReals :: [String] -> Symbolic [SReal]
 sReals = Trans.sReals
 
--- | Declare an 'SFloat'
+-- | Declare a named 'SFloat'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFloat'
 sFloat :: String -> Symbolic SFloat
 sFloat = Trans.sFloat
 
+-- | Declare an unnamed 'SFloat'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFloat_'
+sFloat_ :: Symbolic SFloat
+sFloat_ = Trans.sFloat_
+
 -- | Declare a list of 'SFloat's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sFloats'
 sFloats :: [String] -> Symbolic [SFloat]
 sFloats = Trans.sFloats
 
--- | Declare an 'SDouble'
+-- | Declare a named 'SDouble'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sDouble'
 sDouble :: String -> Symbolic SDouble
 sDouble = Trans.sDouble
 
+-- | Declare an unnamed 'SDouble'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sDouble_'
+sDouble_ :: Symbolic SDouble
+sDouble_ = Trans.sDouble_
+
 -- | Declare a list of 'SDouble's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sDoubles'
 sDoubles :: [String] -> Symbolic [SDouble]
 sDoubles = Trans.sDoubles
 
--- | Declare an 'SChar'
+-- | Declare a named 'SChar'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sChar'
 sChar :: String -> Symbolic SChar
 sChar = Trans.sChar
 
--- | Declare an 'SString'
+-- | Declare an unnamed 'SChar'
 --
--- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sString'
-sString :: String -> Symbolic SString
-sString = Trans.sString
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sChar_'
+sChar_ :: Symbolic SChar
+sChar_ = Trans.sChar_
 
 -- | Declare a list of 'SChar's
 --
@@ -488,36 +567,114 @@
 sChars :: [String] -> Symbolic [SChar]
 sChars = Trans.sChars
 
+-- | Declare a named 'SString'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sString'
+sString :: String -> Symbolic SString
+sString = Trans.sString
+
+-- | Declare an unnamed 'SString'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sString_'
+sString_ :: Symbolic SString
+sString_ = Trans.sString_
+
 -- | Declare a list of 'SString's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sStrings'
 sStrings :: [String] -> Symbolic [SString]
 sStrings = Trans.sStrings
 
--- | Declare an 'SList'
+-- | Declare a named 'SList'
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sList'
 sList :: SymVal a => String -> Symbolic (SList a)
 sList = Trans.sList
 
+-- | Declare an unnamed 'SList'
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sList_'
+sList_ :: SymVal a => Symbolic (SList a)
+sList_ = Trans.sList_
+
 -- | Declare a list of 'SList's
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sLists'
 sLists :: SymVal a => [String] -> Symbolic [SList a]
 sLists = Trans.sLists
 
--- | Declare a tuple.
+-- | Declare a named tuple.
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sTuple'
 sTuple :: SymVal tup => String -> Symbolic (SBV tup)
 sTuple = Trans.sTuple
 
+-- | Declare an unnamed tuple.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sTuple_'
+sTuple_ :: SymVal tup => Symbolic (SBV tup)
+sTuple_ = Trans.sTuple_
+
 -- | Declare a list of tuples.
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sTuples'
 sTuples :: SymVal tup => [String] -> Symbolic [SBV tup]
 sTuples = Trans.sTuples
 
+-- | Declare a named 'Data.SBV.SEither'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sEither'
+sEither :: (SymVal a, SymVal b) => String -> Symbolic (SEither a b)
+sEither = Trans.sEither
+
+-- | Declare an unnamed 'Data.SBV.SEither'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sEither_'
+sEither_ :: (SymVal a, SymVal b) => Symbolic (SEither a b)
+sEither_ = Trans.sEither_
+
+-- | Declare a list of 'Data.SBV.SEither' values.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sEithers'
+sEithers :: (SymVal a, SymVal b) => [String] -> Symbolic [SEither a b]
+sEithers = Trans.sEithers
+
+-- | Declare a named 'Data.SBV.SMaybe'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sMaybe'
+sMaybe :: SymVal a => String -> Symbolic (SMaybe a)
+sMaybe = Trans.sMaybe
+
+-- | Declare an unnamed 'Data.SBV.SMaybe'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sMaybe_'
+sMaybe_ :: SymVal a => Symbolic (SMaybe a)
+sMaybe_ = Trans.sMaybe_
+
+-- | Declare a list of 'Data.SBV.SMaybe' values.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sMaybes'
+sMaybes :: SymVal a => [String] -> Symbolic [SMaybe a]
+sMaybes = Trans.sMaybes
+
+-- | Declare a named 'Data.SBV.SSet'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sSet'
+sSet :: (Ord a, SymVal a) => String -> Symbolic (SSet a)
+sSet = Trans.sSet
+
+-- | Declare an unnamed 'Data.SBV.SSet'.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sSet_'
+sSet_ :: (Ord a, SymVal a) => Symbolic (SSet a)
+sSet_ = Trans.sSet_
+
+-- | Declare a list of 'Data.SBV.SSet' values.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.sSets'
+sSets :: (Ord a, SymVal a) => [String] -> Symbolic [SSet a]
+sSets = Trans.sSets
+
 -- | Form the symbolic conjunction of a given list of boolean conditions. Useful in expressing
 -- problems with constraints, like the following:
 --
@@ -539,13 +696,13 @@
 -- | Minimize a named metric
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.minimize'
-minimize :: Metric a => String -> a -> Symbolic ()
+minimize :: Metric a => String -> SBV a -> Symbolic ()
 minimize = Trans.minimize
 
 -- | Maximize a named metric
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.maximize'
-maximize :: Metric a => String -> a -> Symbolic ()
+maximize :: Metric a => String -> SBV a -> Symbolic ()
 maximize = Trans.maximize
 
 -- Data.SBV.Core.Symbolic:
diff --git a/Data/SBV/Compilers/C.hs b/Data/SBV/Compilers/C.hs
--- a/Data/SBV/Compilers/C.hs
+++ b/Data/SBV/Compilers/C.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Compilers.C
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -191,8 +191,11 @@
                      KString            -> text "%s"
                      KChar              -> text "%c"
                      KList k            -> die $ "list sort: " ++ show k
+                     KSet  k            -> die $ "set sort: " ++ show k
                      KUninterpreted s _ -> die $ "uninterpreted sort: " ++ s
                      KTuple k           -> die $ "tuple sort: " ++ show k
+                     KMaybe  k          -> die $ "maybe sort: "  ++ show k
+                     KEither k1 k2      -> die $ "either sort: " ++ show (k1, k2)
   where spec :: (Bool, Int) -> Doc
         spec (False,  1) = text "%d"
         spec (False,  8) = text "%\"PRIu8\""
@@ -204,9 +207,10 @@
         spec (False, 64) = text "0x%016\"PRIx64\"ULL"
         spec (True,  64) = text "%\"PRId64\"LL"
         spec (s, sz)     = die $ "Format specifier at type " ++ (if s then "SInt" else "SWord") ++ show sz
+
         specF :: CgSRealType -> Doc
-        specF CgFloat      = text "%.6g"    -- float.h: __FLT_DIG__
-        specF CgDouble     = text "%.15g"   -- float.h: __DBL_DIG__
+        specF CgFloat      = text "%a"
+        specF CgDouble     = text "%a"
         specF CgLongDouble = text "%Lf"
 
 -- | Make a constant value of the given type. We don't check for out of bounds here, as it should not be needed.
@@ -372,7 +376,7 @@
               $$  text "}"
               $$  text ""
        nm = text fn
-       pairedInputs = matchRands (map abs randVals) inps
+       pairedInputs = matchRands randVals inps
        matchRands _      []                                 = []
        matchRands []     _                                  = die "Run out of driver values!"
        matchRands (r:rs) ((n, CgAtomic sv)            : cs) = ([mkRVal sv r], n, CgAtomic sv) : matchRands rs cs
@@ -427,6 +431,16 @@
   = error "SBV->C: Strings are currently not supported by the C compiler. Please get in touch if you'd like support for this feature!"
   | KChar `Set.member` kindInfo
   = error "SBV->C: Characters are currently not supported by the C compiler. Please get in touch if you'd like support for this feature!"
+  | any isSet kindInfo
+  = error "SBV->C: Sets (SSet) are currently not supported by the C compiler. Please get in touch if you'd like support for this feature!"
+  | any isList kindInfo
+  = error "SBV->C: Lists (SList) are currently not supported by the C compiler. Please get in touch if you'd like support for this feature!"
+  | any isTuple kindInfo
+  = error "SBV->C: Tuples (STupleN) are currently not supported by the C compiler. Please get in touch if you'd like support for this feature!"
+  | any isMaybe kindInfo
+  = error "SBV->C: Optional (SMaybe) values are currently not supported by the C compiler. Please get in touch if you'd like support for this feature!"
+  | any isEither kindInfo
+  = error "SBV->C: Either (SEither) values are currently not supported by the C compiler. Please get in touch if you'd like support for this feature!"
   | isNothing (cgReal cfg) && KReal `Set.member` kindInfo
   = error $ "SBV->C: SReal values are not supported by the C compiler."
           ++ "\nUse 'cgSRealType' to specify a custom type for SReal representation."
@@ -488,7 +502,10 @@
                       len (KBounded False n)   = 5 + length (show n) -- SWordN
                       len (KBounded True  n)   = 4 + length (show n) -- SIntN
                       len (KList s)            = die $ "List sort: " ++ show s
+                      len (KSet  s)            = die $ "Set sort: " ++ show s
                       len (KTuple s)           = die $ "Tuple sort: " ++ show s
+                      len (KMaybe k)           = die $ "Maybe sort: " ++ show k
+                      len (KEither k1 k2)      = die $ "Either sort: " ++ show (k1, k2)
                       len (KUninterpreted s _) = die $ "Uninterpreted sort: " ++ s
 
                       getMax 8 _      = 8  -- 8 is the max we can get with SInteger, so don't bother looking any further
@@ -583,18 +600,18 @@
   where same f                   = (f, f)
         named fnm dnm f          = (f fnm, f dnm)
 
-        castToUnsigned f to = parens (text "!isnan" P.<> parens a <+> text "&&" <+> text "signbit" P.<> parens a) <+> text "?" <+> cvt1 <+> text ":" <+> cvt2
-          where [a]  = map snd fpArgs
-                absA = text (if f == KFloat then "fabsf" else "fabs") P.<> parens a
-                cvt1 = parens (text "-" <+> parens (parens (text (show to)) <+> absA))
-                cvt2 =                      parens (parens (text (show to)) <+> a)
+        cvt (FP_Cast from to m)     = case checkRM (m `lookup` consts) of
+                                        Nothing          -> cast $ \[a] -> parens (text (show to)) <+> rnd a
+                                        Just (Left  msg) -> die msg
+                                        Just (Right msg) -> tbd msg
+                                      where -- if we're converting from float to some integral like; first use rint/rintf to do the internal conversion and then cast.
+                                            rnd a
+                                             | (isFloat from || isDouble from) && (isBounded to || isUnbounded to)
+                                             = let f = if isFloat from then "rintf" else "rint"
+                                               in text f P.<> parens a
+                                             | True
+                                             = a
 
-        cvt (FP_Cast f to m)     = case checkRM (m `lookup` consts) of
-                                     Nothing          -> if f `elem` [KFloat, KDouble] && not (hasSign to)
-                                                         then castToUnsigned f to
-                                                         else cast $ \[a] -> parens (text (show to)) <+> a
-                                     Just (Left  msg) -> die msg
-                                     Just (Right msg) -> tbd msg
         cvt (FP_Reinterpret f t) = case (f, t) of
                                      (KBounded False 32, KFloat)  -> cast $ cpy "sizeof(SFloat)"
                                      (KBounded False 64, KDouble) -> cast $ cpy "sizeof(SDouble)"
@@ -746,7 +763,10 @@
                                                                        Nothing -> (True, True) -- won't matter, it'll be rejected later
                                                                        Just i  -> (True, canOverflow True i)
                                                KList     s        -> die $ "List sort " ++ show s
+                                               KSet      s        -> die $ "Set sort " ++ show s
                                                KTuple    s        -> die $ "Tuple sort " ++ show s
+                                               KMaybe    ek       -> die $ "Maybe sort " ++ show ek
+                                               KEither   k1 k2    -> die $ "Either sort " ++ show (k1, k2)
                                                KUninterpreted s _ -> die $ "Uninterpreted sort: " ++ s
 
         -- Div/Rem should be careful on 0, in the SBV world x `div` 0 is 0, x `rem` 0 is x
diff --git a/Data/SBV/Compilers/CodeGen.hs b/Data/SBV/Compilers/CodeGen.hs
--- a/Data/SBV/Compilers/CodeGen.hs
+++ b/Data/SBV/Compilers/CodeGen.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Compilers.CodeGen
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/Control.hs b/Data/SBV/Control.hs
--- a/Data/SBV/Control.hs
+++ b/Data/SBV/Control.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Control
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -16,7 +16,7 @@
      -- $queryIntro
 
      -- * User queries
-       ExtractIO(..), MonadQuery(..), Queriable(..), Query, query
+       ExtractIO(..), MonadQuery(..), Queriable(..), Fresh(..), Query, query
 
      -- * Create a fresh variable
      , freshVar_, freshVar
@@ -29,7 +29,7 @@
 
      -- * Querying the solver
      -- ** Extracting values
-     , SMTValue(..), getValue, getUninterpretedValue, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
+     , SMTValue(..), getValue, registerUISMTFunction, getFunction, getUninterpretedValue, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
 
      -- ** Extracting the unsat core
      , getUnsatCore
@@ -76,7 +76,7 @@
      ) where
 
 import Data.SBV.Core.Data     (SMTConfig(..))
-import Data.SBV.Core.Symbolic (MonadQuery(..), Query, Queriable(..), Symbolic, QueryContext(..))
+import Data.SBV.Core.Symbolic (MonadQuery(..), Query, Queriable(..), Fresh(..), Symbolic, QueryContext(..))
 
 import Data.SBV.Control.BaseIO
 import Data.SBV.Control.Query hiding (  getInfo, getOption, getUnknownReason, getObservables
@@ -94,7 +94,7 @@
                                       , freshArray, freshArray_, checkSat, ensureSat
                                       , checkSatUsing, getValue
                                       , getUninterpretedValue, timeout, io)
-import Data.SBV.Control.Utils (SMTValue)
+import Data.SBV.Control.Utils (SMTValue, registerUISMTFunction)
 
 import Data.SBV.Utils.ExtractIO (ExtractIO(..))
 
diff --git a/Data/SBV/Control/BaseIO.hs b/Data/SBV/Control/BaseIO.hs
--- a/Data/SBV/Control/BaseIO.hs
+++ b/Data/SBV/Control/BaseIO.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Control.BaseIO
--- Author    : Brian Schroeder, Levent Erkok
+-- Copyright : (c) Brian Schroeder
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -16,7 +17,7 @@
 import Data.SBV.Control.Types (CheckSatResult, SMTInfoFlag, SMTInfoResponse, SMTOption, SMTReasonUnknown)
 import Data.SBV.Control.Utils (SMTValue)
 import Data.SBV.Core.Concrete (CV)
-import Data.SBV.Core.Data     (HasKind, Symbolic, SymArray, SymVal, SBool, SBV)
+import Data.SBV.Core.Data     (HasKind, Symbolic, SymArray, SymVal, SBool, SBV, SBVType)
 import Data.SBV.Core.Symbolic (Query, QueryContext, QueryState, State, SMTModel, SMTResult, SV)
 
 import qualified Data.SBV.Control.Query as Trans
@@ -52,6 +53,12 @@
 getObservables :: Query [(String, CV)]
 getObservables = Trans.getObservables
 
+-- | Get the uinterpreted constants/functions recorded during a run.
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getUIs'
+getUIs :: Query [(String, SBVType)]
+getUIs = Trans.getUIs
+
 -- | Issue check-sat and get an SMT Result out.
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getSMTResult'
@@ -384,12 +391,24 @@
 getUninterpretedValue :: HasKind a => SBV a -> Query String
 getUninterpretedValue = Trans.getUninterpretedValue
 
+-- | Get the value of an uninterpreted function, as a list of domain, value pairs.
+-- The final value is the "else" clause, i.e., what the function maps values outside
+-- of the domain of the first list.
+getFunction :: Trans.SMTFunction fun a r => fun -> Query ([(a, r)], r)
+getFunction = Trans.getFunction
+
 -- | Get the value of a term. If the kind is Real and solver supports decimal approximations,
 -- we will "squash" the representations.
 --
 -- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getValueCV'
 getValueCV :: Maybe Int -> SV -> Query CV
 getValueCV = Trans.getValueCV
+
+-- | Get the value of an uninterpreted function as an association list
+--
+-- NB. For a version which generalizes over the underlying monad, see 'Data.SBV.Trans.Control.getUIFunCVAssoc'
+getUIFunCVAssoc :: Maybe Int -> (String, SBVType) -> Query ([([CV], CV)], CV)
+getUIFunCVAssoc = Trans.getUIFunCVAssoc
 
 -- | Check for satisfiability.
 --
diff --git a/Data/SBV/Control/Query.hs b/Data/SBV/Control/Query.hs
--- a/Data/SBV/Control/Query.hs
+++ b/Data/SBV/Control/Query.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Control.Query
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -13,7 +13,6 @@
 {-# LANGUAGE NamedFieldPuns      #-}
 {-# LANGUAGE Rank2Types          #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TupleSections       #-}
 
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
@@ -226,9 +225,10 @@
 
 -- | Classify a model based on whether it has unbound objectives or not.
 classifyModel :: SMTConfig -> SMTModel -> SMTResult
-classifyModel cfg m = case filter (not . isRegularCV . snd) (modelObjectives m) of
-                        [] -> Satisfiable cfg m
-                        _  -> SatExtField cfg m
+classifyModel cfg m
+  | any isExt (modelObjectives m) = SatExtField cfg m
+  | True                          = Satisfiable cfg m
+  where isExt (_, v) = not $ isRegularCV v
 
 -- | Generalization of 'Data.SBV.Control.getLexicographicOptResults'
 getLexicographicOptResults :: (MonadIO m, MonadQuery m) => m SMTResult
@@ -272,7 +272,7 @@
                                     Unsat -> return (False, [])
                                     Sat   -> continue (classifyModel cfg)
                                     Unk   -> do ur <- getUnknownReason
-                                                return (False, [ProofError cfg [show ur]])
+                                                return (False, [ProofError cfg [show ur] Nothing])
 
   where continue classify = do m <- getModel
                                (limReached, fronts) <- getParetoFronts (subtract 1 <$> mbN) [m]
@@ -294,38 +294,73 @@
 -- | Get a model stored at an index. This is likely very Z3 specific!
 getModelAtIndex :: (MonadIO m, MonadQuery m) => Maybe Int -> m SMTModel
 getModelAtIndex mbi = do
-             State{runMode} <- queryState
-             cfg    <- getConfig
-             inps   <- getQuantifiedInputs
-             obsvs  <- getObservables
-             rm     <- io $ readIORef runMode
-             assocs <- case rm of
-                         m@CodeGen         -> error $ "SBV.getModel: Model is not available in mode: " ++ show m
-                         m@Concrete        -> error $ "SBV.getModel: Model is not available in mode: " ++ show m
-                         SMTMode _ isSAT _ -> -- for "sat", display the prefix existentials. for "proof", display the prefix universals
-                                              let allModelInputs = if isSAT then takeWhile ((/= ALL) . fst) inps
-                                                                            else takeWhile ((== ALL) . fst) inps
+    State{runMode} <- queryState
+    rm     <- io $ readIORef runMode
+    case rm of
+      m@CodeGen           -> error $ "SBV.getModel: Model is not available in mode: " ++ show m
+      m@Concrete{}        -> error $ "SBV.getModel: Model is not available in mode: " ++ show m
+      SMTMode _ _ isSAT _ -> do
+          cfg   <- getConfig
+          inps  <- getQuantifiedInputs
+          obsvs <- getObservables
+          uis   <- getUIs
 
-                                                  -- are we inside a quantifier
-                                                  insideQuantifier = length allModelInputs < length inps
+           -- for "sat", display the prefix existentials. for "proof", display the prefix universals
+          let allModelInputs = if isSAT then takeWhile ((/= ALL) . fst) inps
+                                        else takeWhile ((== ALL) . fst) inps
 
-                                                  -- observables are only meaningful if we're not in a quantified context
-                                                  prefixObservables | insideQuantifier = []
-                                                                    | True             = obsvs
+              -- are we inside a quantifier
+              insideQuantifier = length allModelInputs < length inps
 
-                                                  sortByNodeId :: [(NamedSymVar, a)] -> [a]
-                                                  sortByNodeId = map snd . sortBy (compare `on` (\((SV _ nid, _), _) -> nid))
+              -- observables are only meaningful if we're not in a quantified context
+              prefixObservables | insideQuantifier = []
+                                | True             = obsvs
 
-                                                  grab (sv, nm) = ((sv, nm),) <$> getValueCV mbi sv
+              sortByNodeId :: [(SV, (String, CV))] -> [(String, CV)]
+              sortByNodeId = map snd . sortBy (compare `on` (\(SV _ nid, _) -> nid))
 
-                                              in do inputAssocs <- mapM (grab . snd) allModelInputs
-                                                    return $  sortOn fst prefixObservables
-                                                           ++ sortByNodeId [(sv, (nm, val)) | (sv@(_, nm), val) <- inputAssocs, not (isNonModelVar cfg nm)]
+              grab (sv, nm) = wrap <$> getValueCV mbi sv
+                 where wrap c = (sv, (nm, c))
 
-             return SMTModel { modelObjectives = []
-                             , modelAssocs     = assocs
-                             }
+          inputAssocs <- mapM (grab . snd) allModelInputs
 
+          let assocs =  sortOn fst prefixObservables
+                     ++ sortByNodeId [p | p@(_, (nm, _)) <- inputAssocs, not (isNonModelVar cfg nm)]
+
+          -- collect UIs if requested
+          let uiFuns = [ui | ui@(_, SBVType as) <- uis, length as > 1, satTrackUFs cfg] -- functions have at least two things in their type!
+
+          -- If there are uninterpreted functions, arrange so that z3's pretty-printer flattens things out
+          -- as cex's tend to get larger
+          unless (null uiFuns) $
+             let solverCaps = capabilities (solver cfg)
+             in case supportsFlattenedModels solverCaps of
+                  Nothing   -> return ()
+                  Just cmds -> mapM_ (send True) cmds
+
+          bindings <- let get i@(ALL, _)      = return (i, Nothing)
+                          get i@(EX, (sv, _)) = case sv `lookup` inputAssocs of
+                                                  Just (_, cv) -> return (i, Just cv)
+                                                  Nothing      -> do cv <- getValueCV mbi sv
+                                                                     return (i, Just cv)
+
+                          flipQ i@(q, sv) = case (isSAT, q) of
+                                             (True,  _ )  -> i
+                                             (False, EX)  -> (ALL, sv)
+                                             (False, ALL) -> (EX,  sv)
+
+                      in if validateModel cfg
+                         then Just <$> mapM (get . flipQ) inps
+                         else return Nothing
+
+          uivs <- mapM (\ui@(nm, t) -> (\a -> (nm, (t, a))) <$> getUIFunCVAssoc mbi ui) uiFuns
+
+          return SMTModel { modelObjectives = []
+                          , modelBindings   = bindings
+                          , modelAssocs     = assocs
+                          , modelUIFuns     = uivs
+                          }
+
 -- | Just after a check-sat is issued, collect objective values. Used
 -- internally only, not exposed to the user.
 getObjectiveValues :: forall m. (MonadIO m, MonadQuery m) => m [(String, GeneralizedCV)]
@@ -344,39 +379,18 @@
         getObjValue :: (forall a. Maybe [String] -> m a) -> [NamedSymVar] -> SExpr -> m (Maybe (String, GeneralizedCV))
         getObjValue bailOut inputs expr =
                 case expr of
-                  EApp [_]                                            -> return Nothing            -- Happens when a soft-assertion has no associated group.
-                  EApp [ECon nm, v]                                   -> locate nm v Nothing       -- Regular case
-                  EApp [EApp [ECon "bvadd", ECon nm, ENum (a, _)], v] -> locate nm v (Just a)      -- Happens when we "adjust" a signed-bounded objective
-                  _                                                   -> dontUnderstand (show expr)
+                  EApp [_]          -> return Nothing            -- Happens when a soft-assertion has no associated group.
+                  EApp [ECon nm, v] -> locate nm v               -- Regular case
+                  _                 -> dontUnderstand (show expr)
 
-          where locate nm v mbAdjust = case listToMaybe [p | p@(sv, _) <- inputs, show sv == nm] of
-                                         Nothing               -> return Nothing -- Happens when the soft assertion has a group-id that's not one of the input names
-                                         Just (sv, actualName) -> grab sv v >>= \val -> return $ Just (actualName, signAdjust mbAdjust val)
+          where locate nm v = case listToMaybe [p | p@(sv, _) <- inputs, show sv == nm] of
+                                Nothing               -> return Nothing -- Happens when the soft assertion has a group-id that's not one of the input names
+                                Just (sv, actualName) -> grab sv v >>= \val -> return $ Just (actualName, val)
 
                 dontUnderstand s = bailOut $ Just [ "Unable to understand solver output."
                                                   , "While trying to process: " ++ s
                                                   ]
 
-                signAdjust :: Maybe Integer -> GeneralizedCV -> GeneralizedCV
-                signAdjust Nothing    v = v
-                signAdjust (Just adj) e = goG e
-                  where goG :: GeneralizedCV -> GeneralizedCV
-                        goG (ExtendedCV ecv) = ExtendedCV $ goE ecv
-                        goG (RegularCV  cv)  = RegularCV  $ go cv
-
-                        goE :: ExtCV -> ExtCV
-                        goE (Infinite k)      = Infinite k
-                        goE (Epsilon  k)      = Epsilon  k
-                        goE (Interval  lo hi) = Interval  (goE lo) (goE hi)
-                        goE (BoundedCV cv)    = BoundedCV (go cv)
-                        goE (AddExtCV  a b)   = AddExtCV  (goE a) (goE b)
-                        goE (MulExtCV  a b)   = MulExtCV  (goE a) (goE b)
-
-                        go :: CV -> CV
-                        go cv = case (kindOf cv, cvVal cv) of
-                                  (k@(KBounded True _), CInteger v) -> normCV $ CV k (CInteger (v - adj))
-                                  _                                 -> error $ "SBV.getObjValue: Unexpected cv received! " ++ show cv
-
                 grab :: SV -> SExpr -> m GeneralizedCV
                 grab s topExpr
                   | Just v <- recoverKindedValue k topExpr = return $ RegularCV v
@@ -721,6 +735,9 @@
                 r                      -> error $ "Data.SBV: Impossible happened in |->: Cannot construct a CV with literal: " ++ show r
 
 -- | Generalization of 'Data.SBV.Control.mkSMTResult'
+-- NB. This function does not allow users to create interpretations for UI-Funs. But that's
+-- probably not a good idea anyhow. Also, if you use the 'validateModel' feature, SBV will
+-- fail on models returned via this function.
 mkSMTResult :: (MonadIO m, MonadQuery m) => [Assignment] -> m SMTResult
 mkSMTResult asgns = do
              QueryState{queryConfig} <- getQueryState
@@ -782,7 +799,11 @@
              assocs <- inNewContext grabValues
 
              let m = SMTModel { modelObjectives = []
+                              , modelBindings   = Nothing
                               , modelAssocs     = assocs
+                              , modelUIFuns     = []
                               }
 
              return $ Satisfiable queryConfig m
+
+{-# ANN getModelAtIndex ("HLint: ignore Use forM_"          :: String) #-}
diff --git a/Data/SBV/Control/Types.hs b/Data/SBV/Control/Types.hs
--- a/Data/SBV/Control/Types.hs
+++ b/Data/SBV/Control/Types.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Control.Types
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/Control/Utils.hs b/Data/SBV/Control/Utils.hs
--- a/Data/SBV/Control/Utils.hs
+++ b/Data/SBV/Control/Utils.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Control.Utils
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,23 +9,26 @@
 -- Query related utils.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE BangPatterns          #-}
-{-# LANGUAGE DefaultSignatures     #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE LambdaCase            #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE NamedFieldPuns        #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-{-# LANGUAGE TupleSections         #-}
-{-# LANGUAGE TypeApplications      #-}
-{-# LANGUAGE TypeSynonymInstances  #-}
+{-# LANGUAGE BangPatterns           #-}
+{-# LANGUAGE DefaultSignatures      #-}
+{-# LANGUAGE FlexibleContexts       #-}
+{-# LANGUAGE FlexibleInstances      #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE LambdaCase             #-}
+{-# LANGUAGE NamedFieldPuns         #-}
+{-# LANGUAGE ScopedTypeVariables    #-}
+{-# LANGUAGE TupleSections          #-}
+{-# LANGUAGE TypeApplications       #-}
 
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Data.SBV.Control.Utils (
        io
-     , ask, send, getValue, getUninterpretedValue, getValueCV, getUnsatAssumptions, SMTValue(..)
-     , getQueryState, modifyQueryState, getConfig, getObjectives, getSBVAssertions, getSBVPgm, getQuantifiedInputs, getObservables
+     , ask, send, getValue, getFunction, getUninterpretedValue
+     , getValueCV, getUIFunCVAssoc, getUnsatAssumptions
+     , SMTValue(..), SMTFunction(..), registerUISMTFunction
+     , getQueryState, modifyQueryState, getConfig, getObjectives, getUIs
+     , getSBVAssertions, getSBVPgm, getQuantifiedInputs, getObservables
      , checkSat, checkSatUsing, getAllSatResult
      , inNewContext, freshVar, freshVar_, freshArray, freshArray_
      , parse
@@ -39,7 +42,7 @@
      ) where
 
 import Data.Maybe (isJust)
-import Data.List  (sortBy, sortOn, elemIndex, partition, groupBy, tails, intercalate)
+import Data.List  (sortBy, sortOn, elemIndex, partition, groupBy, tails, intercalate, nub, sort)
 
 import Data.Char     (isPunctuation, isSpace, chr, ord, isDigit)
 import Data.Function (on)
@@ -52,8 +55,9 @@
 
 import qualified Data.Map.Strict    as Map
 import qualified Data.IntMap.Strict as IMap
+import qualified Data.Sequence      as S
 
-import Control.Monad            (join, unless)
+import Control.Monad            (join, unless, zipWithM, when, replicateM)
 import Control.Monad.IO.Class   (MonadIO, liftIO)
 import Control.Monad.Trans      (lift)
 import Control.Monad.Reader     (runReaderT)
@@ -69,27 +73,33 @@
                               , newExpr, SBVExpr(..), Op(..), FPOp(..), SBV(..), SymArray(..)
                               , SolverContext(..), SBool, Objective(..), SolverCapabilities(..), capabilities
                               , Result(..), SMTProblem(..), trueSV, SymVal(..), SBVPgm(..), SMTSolver(..), SBVRunMode(..)
+                              , SBVType(..), forceSVArg, RoundingMode(RoundNearestTiesToEven), (.=>)
+                              , RCSet(..)
                               )
 
 import Data.SBV.Core.Symbolic ( IncState(..), withNewIncState, State(..), svToSV, symbolicEnv, SymbolicT
-                              , MonadQuery(..), QueryContext(..), Queriable(..)
+                              , MonadQuery(..), QueryContext(..), Queriable(..), Fresh(..)
                               , registerLabel, svMkSymVar
                               , isSafetyCheckingIStage, isSetupIStage, isRunIStage, IStage(..), QueryT(..)
-                              , extractSymbolicSimulationState
+                              , extractSymbolicSimulationState, MonadSymbolic(..), newUninterpreted
                               )
 
 import Data.SBV.Core.AlgReals   (mergeAlgReals)
+import Data.SBV.Core.Kind       (smtType, hasUninterpretedSorts)
 import Data.SBV.Core.Operations (svNot, svNotEqual, svOr)
 
+import Data.SBV.SMT.SMT     (showModel, parseCVs, SatModel)
 import Data.SBV.SMT.SMTLib  (toIncSMTLib, toSMTLib)
 import Data.SBV.SMT.Utils   (showTimeoutValue, addAnnotations, alignPlain, debug, mergeSExpr, SBVException(..))
 
 import Data.SBV.Utils.ExtractIO
-import Data.SBV.Utils.Lib (qfsToString, isKString)
+import Data.SBV.Utils.Lib       (qfsToString, isKString)
 import Data.SBV.Utils.SExpr
+import Data.SBV.Utils.PrettyNum (cvToSMTLib)
+
 import Data.SBV.Control.Types
 
-import qualified Data.Set as Set (toList)
+import qualified Data.Set as Set (empty, fromList, toAscList, map)
 
 import qualified Control.Exception as C
 
@@ -103,6 +113,7 @@
    softConstrain          = addQueryConstraint True  []
    namedConstraint nm     = addQueryConstraint False [(":named", nm)]
    constrainWithAttribute = addQueryConstraint False
+   contextState           = queryState
 
    setOption o
      | isStartModeOption o = error $ unlines [ ""
@@ -152,15 +163,16 @@
         ls  <- io $ do let swap  (a, b)        = (b, a)
                            cmp   (a, _) (b, _) = a `compare` b
                            arrange (i, (at, rt, es)) = ((i, at, rt), es)
-                       inps  <- reverse <$> readIORef (rNewInps is)
-                       ks    <- readIORef (rNewKinds is)
-                       cnsts <- sortBy cmp . map swap . Map.toList <$> readIORef (rNewConsts is)
-                       arrs  <- IMap.toAscList <$> readIORef (rNewArrs is)
-                       tbls  <- map arrange . sortBy cmp . map swap . Map.toList <$> readIORef (rNewTbls is)
-                       uis   <- Map.toAscList <$> readIORef (rNewUIs is)
-                       as    <- readIORef (rNewAsgns is)
+                       inps        <- reverse <$> readIORef (rNewInps is)
+                       ks          <- readIORef (rNewKinds is)
+                       cnsts       <- sortBy cmp . map swap . Map.toList <$> readIORef (rNewConsts is)
+                       arrs        <- IMap.toAscList <$> readIORef (rNewArrs is)
+                       tbls        <- map arrange . sortBy cmp . map swap . Map.toList <$> readIORef (rNewTbls is)
+                       uis         <- Map.toAscList <$> readIORef (rNewUIs is)
+                       as          <- readIORef (rNewAsgns is)
+                       constraints <- readIORef (rNewConstraints is)
 
-                       return $ toIncSMTLib afterAPush cfg inps ks cnsts arrs tbls uis as cfg
+                       return $ toIncSMTLib afterAPush cfg inps ks cnsts arrs tbls uis as constraints cfg
         mapM_ (send True) $ mergeSExpr ls
 
 -- | Retrieve the query context
@@ -199,9 +211,16 @@
 
 -- | Generic 'Queriable' instance for 'SymVal'/'SMTValue' values
 instance (MonadIO m, SymVal a, SMTValue a) => Queriable m (SBV a) a where
-  fresh   = freshVar_
-  extract = getValue
+  create  = freshVar_
+  project = getValue
+  embed   = return . literal
 
+-- | Generic 'Queriable' instance for things that are 'Fresh' and look like containers:
+instance (MonadIO m, SymVal a, SMTValue a, Foldable t, Traversable t, Fresh m (t (SBV a))) => Queriable m (t (SBV a)) (t a) where
+  create  = fresh
+  project = mapM getValue
+  embed   = return . fmap literal
+
 -- | Generalization of 'Data.SBV.Control.freshVar_'
 freshVar_ :: forall a m. (MonadIO m, MonadQuery m, SymVal a) => m (SBV a)
 freshVar_ = inNewContext $ fmap SBV . svMkSymVar (Just EX) k Nothing
@@ -287,7 +306,9 @@
 
                                            unexpected cmd s "success" Nothing r Nothing
 
-               else io $ querySend queryTimeOutValue s  -- fire and forget. if you use this, you're on your own!
+               else do -- fire and forget. if you use this, you're on your own!
+                       queryDebug ["[FIRE] " `alignPlain` s]
+                       io $ querySend queryTimeOutValue s
 
 -- | Generalization of 'Data.SBV.Control.retrieveResponse'
 retrieveResponse :: (MonadIO m, MonadQuery m) => String -> Maybe Int -> m [String]
@@ -390,10 +411,33 @@
 
    sexprToVal _                                       = Nothing
 
+instance (SMTValue a, SMTValue b) => SMTValue (Either a b) where
+  sexprToVal (EApp [ECon "left_SBVEither",  a])                      = Left  <$> sexprToVal a
+  sexprToVal (EApp [ECon "right_SBVEither", b])                      = Right <$> sexprToVal b
+  sexprToVal (EApp [EApp [ECon "as", ECon "left_SBVEither",  _], a]) = Left  <$> sexprToVal a   -- CVC4 puts full ascriptions
+  sexprToVal (EApp [EApp [ECon "as", ECon "right_SBVEither", _], b]) = Right <$> sexprToVal b   -- CVC4 puts full ascriptions
+  sexprToVal _                                                       = Nothing
+
+instance SMTValue a => SMTValue (Maybe a) where
+  sexprToVal (ECon "nothing_SBVMaybe")                                = return Nothing
+  sexprToVal (EApp [ECon "just_SBVMaybe", a])                         = Just <$> sexprToVal a
+  sexprToVal (      EApp [ECon "as", ECon "nothing_SBVMaybe", _])     = return Nothing          -- Ditto here for CVC4
+  sexprToVal (EApp [EApp [ECon "as", ECon "just_SBVMaybe",    _], a]) = Just <$> sexprToVal a
+  sexprToVal _                                                        = Nothing
+
 instance SMTValue () where
-   sexprToVal (ECon "SBVTuple0") = Just ()
-   sexprToVal _                  = Nothing
+   sexprToVal (ECon "mkSBVTuple0") = Just ()
+   sexprToVal _                    = Nothing
 
+instance (Ord a, SymVal a) => SMTValue (RCSet a) where
+   sexprToVal e = recoverKindedValue k e >>= cvt . cvVal
+     where ke = kindOf (Proxy @a)
+           k  = KSet ke
+
+           cvt (CSet (RegularSet s))    = Just $ RegularSet    $ Set.map (fromCV . CV ke) s
+           cvt (CSet (ComplementSet s)) = Just $ ComplementSet $ Set.map (fromCV . CV ke) s
+           cvt _                        = Nothing
+
 -- | Convert a sexpr of n-tuple to constituent sexprs. Z3 and CVC4 differ here on how they
 -- present tuples, so we accommodate both:
 sexprToTuple :: Int -> SExpr -> [SExpr]
@@ -455,12 +499,346 @@
                 let nm  = show sv
                     cmd = "(get-value (" ++ nm ++ "))"
                     bad = unexpected "getValue" cmd "a model value" Nothing
+
                 r <- ask cmd
-                parse r bad $ \case EApp [EApp [ECon o,  v]] | o == show sv -> case sexprToVal v of
-                                                                                 Nothing -> bad r Nothing
-                                                                                 Just c  -> return c
-                                    _                                       -> bad r Nothing
 
+                let extract v = case sexprToVal v of
+                                  Nothing -> bad r Nothing
+                                  Just c  -> return c
+
+                -- Along with regular extractions, also handle the oddball case of true/false request. These
+                -- can come from queries, so we have to handle it specifically here.
+                parse r bad $ \case EApp [EApp [ECon o,  v]]                   | o == show sv                                             -> extract v
+                                    EApp [EApp [ENum (i, _), v@(ENum (j, _))]] | sv `elem` [falseSV, trueSV] && i `elem` [0, 1] && i == j -> extract v
+                                    _                                                                                                     -> bad r Nothing
+
+-- | A class which allows for sexpr-conversion to functions
+class (HasKind r, SatModel r, SMTValue r) => SMTFunction fun a r | fun -> a r where
+  sexprToArg     :: fun -> [SExpr] -> Maybe a
+  smtFunName     :: (MonadIO m, SolverContext m, MonadSymbolic m) => fun -> m String
+  smtFunSaturate :: fun -> SBV r
+  smtFunType     :: fun -> SBVType
+  smtFunDefault  :: fun -> Maybe r
+  sexprToFun     :: (MonadIO m, SolverContext m, MonadQuery m, MonadSymbolic m) => fun -> SExpr -> m (Maybe ([(a, r)], r))
+
+  {-# MINIMAL sexprToArg, smtFunSaturate, smtFunType  #-}
+
+  -- Given the function, figure out a default "return value"
+  smtFunDefault _
+    | Just v <- defaultKindedValue (kindOf (Proxy @r)), Just (res, []) <- parseCVs [v]
+    = Just res
+    | True
+    = Nothing
+
+  -- Given the function, determine what its name is and do some sanity checks
+  smtFunName f = do st@State{rUIMap} <- contextState
+                    uiMap <- liftIO $ readIORef rUIMap
+                    findName st uiMap
+    where findName st@State{spgm} uiMap = do
+             r <- liftIO $ sbvToSV st (smtFunSaturate f)
+             liftIO $ forceSVArg r
+             SBVPgm asgns <- liftIO $ readIORef spgm
+
+             let cantFind = error $ unlines $    [ ""
+                                                 , "*** Data.SBV.getFunction: Must be called on an uninterpreted function!"
+                                                 , "***"
+                                                 , "***    Expected to receive a function created by \"uninterpret\""
+                                                 ]
+                                              ++ tag
+                                              ++ [ "***"
+                                                 , "*** Make sure to call getFunction on uninterpreted functions only!"
+                                                 , "*** If that is already the case, please report this as a bug."
+                                                 ]
+                      where tag = case map fst (Map.toList uiMap) of
+                                    []    -> [ "***    But, there are no matching uninterpreted functions in the context." ]
+                                    [x]   -> [ "***    The only possible candidate is: " ++ x ]
+                                    cands -> [ "***    Candidates are:"
+                                             , "***        " ++ intercalate ", " cands
+                                             ]
+
+             case S.findIndexR ((== r) . fst) asgns of
+               Nothing -> cantFind
+               Just i  -> case asgns `S.index` i of
+                            (sv, SBVApp (Uninterpreted nm) _) | r == sv -> return nm
+                            _                                           -> cantFind
+
+  sexprToFun f e = do nm <- smtFunName f
+                      case parseSExprFunction e of
+                        Just (Left nm') -> case (nm == nm', smtFunDefault f) of
+                                             (True, Just v)  -> return $ Just ([], v)
+                                             _               -> bailOut nm
+                        Just (Right v)  -> return $ convert v
+                        Nothing         -> do mbPVS <- pointWiseExtract nm (smtFunType f)
+                                              return $ mbPVS >>= convert
+    where convert    (vs, d) = (,) <$> mapM sexprPoint vs <*> sexprToVal d
+          sexprPoint (as, v) = (,) <$> sexprToArg f as    <*> sexprToVal v
+
+          bailOut nm = error $ unlines [ ""
+                                       , "*** Data.SBV.getFunction: Unable to extract an interpretation for function " ++ show nm
+                                       , "***"
+                                       , "*** Failed while trying to extract a pointwise interpretation."
+                                       , "***"
+                                       , "*** This could be a bug with SBV or the backend solver. Please report!"
+                                       ]
+
+-- | Registering an uninterpreted SMT function. This is typically not necessary as uses of the UI
+-- function itself will register it automatically. But there are cases where doing this explicitly can
+-- come in handy.
+registerUISMTFunction :: (MonadIO m, SolverContext m, MonadSymbolic m) => SMTFunction fun a r => fun -> m ()
+registerUISMTFunction f = do st <- contextState
+                             nm <- smtFunName f
+                             io $ newUninterpreted st nm (smtFunType f) Nothing
+
+-- | Pointwise function value extraction. If we get unlucky and can't parse z3's output (happens
+-- when we have all booleans and z3 decides to spit out an expression), just brute force our
+-- way out of it. Note that we only do this if we have a pure boolean type, as otherwise we'd blow
+-- up. And I think it'll only be necessary then, I haven't seen z3 try anything smarter in other scenarios.
+pointWiseExtract ::  forall m. (MonadIO m, MonadQuery m) => String -> SBVType -> m (Maybe ([([SExpr], SExpr)], SExpr))
+pointWiseExtract nm typ
+   | isBoolFunc
+   = tryPointWise
+   | True
+   = error $ unlines [ ""
+                     , "*** Data.SBV.getFunction: Unsupported: Extracting interpretation for function:"
+                     , "***"
+                     , "***     " ++ nm ++ " :: " ++ show typ
+                     , "***"
+                     , "*** At this time, the expression returned by the solver is too complicated for SBV!"
+                     , "***"
+                     , "*** You can ignore uninterpreted function models for sat models using the 'satTrackUFs' parameter:"
+                     , "***"
+                     , "***             satWith    z3{satTrackUFs = False}"
+                     , "***             allSatWith z3{satTrackUFs = False}"
+                     , "***"
+                     , "*** You can see the response from the solver by running with '{verbose = True}' option."
+                     , "***"
+                     , "*** NB. If this is a use case you'd like SBV to support, please get in touch!"
+                     ]
+  where trueSExpr  = ENum (1, Nothing)
+        falseSExpr = ENum (0, Nothing)
+
+        isTrueSExpr (ENum (1, Nothing)) = True
+        isTrueSExpr (ENum (0, Nothing)) = False
+        isTrueSExpr s                   = error $ "Data.SBV.pointWiseExtract: Impossible happened: Received: " ++ show s
+
+        (nArgs, isBoolFunc) = case typ of
+                                SBVType ts -> (length ts - 1, all (== KBool) ts)
+
+        getBVal :: [SExpr] -> m ([SExpr], SExpr)
+        getBVal args = do let shc c | isTrueSExpr c = "true"
+                                    | True          = "false"
+
+                              as = unwords $ map shc args
+
+                              cmd   = "(get-value ((" ++ nm ++ " " ++ as ++ ")))"
+
+                              bad   = unexpected "get-value" cmd ("pointwise value of boolean function " ++ nm ++ " on " ++ show as) Nothing
+
+                          r <- ask cmd
+
+                          parse r bad $ \case EApp [EApp [_, e]] -> return (args, e)
+                                              _                  -> bad r Nothing
+
+        getBVals :: m [([SExpr], SExpr)]
+        getBVals = mapM getBVal $ replicateM nArgs [falseSExpr, trueSExpr]
+
+        tryPointWise
+          | not isBoolFunc
+          = return Nothing
+          | nArgs < 1
+          = error $ "Data.SBV.pointWiseExtract: Impossible happened, nArgs < 1: " ++ show nArgs ++ " type: " ++ show typ
+          | True
+          = do vs <- getBVals
+               -- Pick the value that will give us the fewer entries
+               let (trues, falses) = partition (\(_, v) -> isTrueSExpr v) vs
+               return $ Just $ if length trues <= length falses
+                               then (trues,  falseSExpr)
+                               else (falses, trueSExpr)
+
+-- | For saturation purposes, get a proper argument. The forall quantification
+-- is safe here since we only use in smtFunSaturate calls, which looks at the
+-- kind stored inside only.
+mkArg :: forall a. Kind -> SBV a
+mkArg k = case defaultKindedValue k of
+            Nothing -> error $ unlines [ ""
+                                       , "*** Data.SBV.smtFunSaturate: Impossible happened!"
+                                       , "*** Unable to create a valid parameter for kind: " ++ show k
+                                       , "*** Please report this as an SBV bug!"
+                                       ]
+            Just c -> SBV $ SVal k (Left c)
+
+-- | Functions of arity 1
+instance ( SymVal a, HasKind a, SMTValue a
+         , SatModel r, HasKind r, SMTValue r
+         ) => SMTFunction (SBV a -> SBV r) a r
+         where
+  sexprToArg _ [a0] = sexprToVal a0
+  sexprToArg _ _    = Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f $ mkArg (kindOf (Proxy @a))
+
+-- | Functions of arity 2
+instance ( SymVal a,  HasKind a, SMTValue a
+         , SymVal b,  HasKind b, SMTValue b
+         , SatModel r, HasKind r, SMTValue r
+         ) => SMTFunction (SBV a -> SBV b -> SBV r) (a, b) r
+         where
+  sexprToArg _ [a0, a1] = (,) <$> sexprToVal a0 <*> sexprToVal a1
+  sexprToArg _ _        = Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkArg (kindOf (Proxy @a)))
+                       (mkArg (kindOf (Proxy @b)))
+
+-- | Functions of arity 3
+instance ( SymVal a,   HasKind a, SMTValue a
+         , SymVal b,   HasKind b, SMTValue b
+         , SymVal c,   HasKind c, SMTValue c
+         , SatModel r, HasKind r, SMTValue r
+         ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV r) (a, b, c) r
+         where
+  sexprToArg _ [a0, a1, a2] = (,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2
+  sexprToArg _ _            = Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkArg (kindOf (Proxy @a)))
+                       (mkArg (kindOf (Proxy @b)))
+                       (mkArg (kindOf (Proxy @c)))
+
+-- | Functions of arity 4
+instance ( SymVal a,   HasKind a, SMTValue a
+         , SymVal b,   HasKind b, SMTValue b
+         , SymVal c,   HasKind c, SMTValue c
+         , SymVal d,   HasKind d, SMTValue d
+         , SatModel r, HasKind r, SMTValue r
+         ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV r) (a, b, c, d) r
+         where
+  sexprToArg _ [a0, a1, a2, a3] = (,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3
+  sexprToArg _ _               = Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkArg (kindOf (Proxy @a)))
+                       (mkArg (kindOf (Proxy @b)))
+                       (mkArg (kindOf (Proxy @c)))
+                       (mkArg (kindOf (Proxy @d)))
+
+-- | Functions of arity 5
+instance ( SymVal a,   HasKind a, SMTValue a
+         , SymVal b,   HasKind b, SMTValue b
+         , SymVal c,   HasKind c, SMTValue c
+         , SymVal d,   HasKind d, SMTValue d
+         , SymVal e,   HasKind e, SMTValue e
+         , SatModel r, HasKind r, SMTValue r
+         ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV r) (a, b, c, d, e) r
+         where
+  sexprToArg _ [a0, a1, a2, a3, a4] = (,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4
+  sexprToArg _ _                    = Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkArg (kindOf (Proxy @a)))
+                       (mkArg (kindOf (Proxy @b)))
+                       (mkArg (kindOf (Proxy @c)))
+                       (mkArg (kindOf (Proxy @d)))
+                       (mkArg (kindOf (Proxy @e)))
+
+-- | Functions of arity 6
+instance ( SymVal a,   HasKind a, SMTValue a
+         , SymVal b,   HasKind b, SMTValue b
+         , SymVal c,   HasKind c, SMTValue c
+         , SymVal d,   HasKind d, SMTValue d
+         , SymVal e,   HasKind e, SMTValue e
+         , SymVal f,   HasKind f, SMTValue f
+         , SatModel r, HasKind r, SMTValue r
+         ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> SBV r) (a, b, c, d, e, f) r
+         where
+  sexprToArg _ [a0, a1, a2, a3, a4, a5] = (,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5
+  sexprToArg _ _                        = Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkArg (kindOf (Proxy @a)))
+                       (mkArg (kindOf (Proxy @b)))
+                       (mkArg (kindOf (Proxy @c)))
+                       (mkArg (kindOf (Proxy @d)))
+                       (mkArg (kindOf (Proxy @e)))
+                       (mkArg (kindOf (Proxy @f)))
+
+-- | Functions of arity 7
+instance ( SymVal a,   HasKind a, SMTValue a
+         , SymVal b,   HasKind b, SMTValue b
+         , SymVal c,   HasKind c, SMTValue c
+         , SymVal d,   HasKind d, SMTValue d
+         , SymVal e,   HasKind e, SMTValue e
+         , SymVal f,   HasKind f, SMTValue f
+         , SymVal g,   HasKind g, SMTValue g
+         , SatModel r, HasKind r, SMTValue r
+         ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> SBV g -> SBV r) (a, b, c, d, e, f, g) r
+         where
+  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6] = (,,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5 <*> sexprToVal a6
+  sexprToArg _ _                            = Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkArg (kindOf (Proxy @a)))
+                       (mkArg (kindOf (Proxy @b)))
+                       (mkArg (kindOf (Proxy @c)))
+                       (mkArg (kindOf (Proxy @d)))
+                       (mkArg (kindOf (Proxy @e)))
+                       (mkArg (kindOf (Proxy @f)))
+                       (mkArg (kindOf (Proxy @g)))
+
+-- | Functions of arity 8
+instance ( SymVal a,   HasKind a, SMTValue a
+         , SymVal b,   HasKind b, SMTValue b
+         , SymVal c,   HasKind c, SMTValue c
+         , SymVal d,   HasKind d, SMTValue d
+         , SymVal e,   HasKind e, SMTValue e
+         , SymVal f,   HasKind f, SMTValue f
+         , SymVal g,   HasKind g, SMTValue g
+         , SymVal h,   HasKind h, SMTValue h
+         , SatModel r, HasKind r, SMTValue r
+         ) => SMTFunction (SBV a -> SBV b -> SBV c -> SBV d -> SBV e -> SBV f -> SBV g -> SBV h -> SBV r) (a, b, c, d, e, f, g, h) r
+         where
+  sexprToArg _ [a0, a1, a2, a3, a4, a5, a6, a7] = (,,,,,,,) <$> sexprToVal a0 <*> sexprToVal a1 <*> sexprToVal a2 <*> sexprToVal a3 <*> sexprToVal a4 <*> sexprToVal a5 <*> sexprToVal a6 <*> sexprToVal a7
+  sexprToArg _ _                                = Nothing
+
+  smtFunType _ = SBVType [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g), kindOf (Proxy @h), kindOf (Proxy @r)]
+
+  smtFunSaturate f = f (mkArg (kindOf (Proxy @a)))
+                       (mkArg (kindOf (Proxy @b)))
+                       (mkArg (kindOf (Proxy @c)))
+                       (mkArg (kindOf (Proxy @d)))
+                       (mkArg (kindOf (Proxy @e)))
+                       (mkArg (kindOf (Proxy @f)))
+                       (mkArg (kindOf (Proxy @g)))
+                       (mkArg (kindOf (Proxy @h)))
+
+-- | Generalization of 'Data.SBV.Control.getFunction'
+getFunction :: (MonadIO m, MonadQuery m, SolverContext m, MonadSymbolic m, SMTFunction fun a r) => fun -> m ([(a, r)], r)
+getFunction f = do nm <- smtFunName f
+
+                   let cmd = "(get-value (" ++ nm ++ "))"
+                       bad = unexpected "getFunction" cmd "a function value" Nothing
+
+                   r <- ask cmd
+
+                   parse r bad $ \case EApp [EApp [ECon o, e]] | o == nm -> do mbAssocs <- sexprToFun f e
+                                                                               case mbAssocs of
+                                                                                 Just assocs -> return assocs
+                                                                                 Nothing     -> do mbPVS <- pointWiseExtract nm (smtFunType f)
+                                                                                                   case mbPVS >>= convert of
+                                                                                                     Just x  -> return x
+                                                                                                     Nothing -> bad r Nothing
+                                       _                                 -> bad r Nothing
+    where convert    (vs, d) = (,) <$> mapM sexprPoint vs <*> sexprToVal d
+          sexprPoint (as, v) = (,) <$> sexprToArg f as    <*> sexprToVal v
+
 -- | Generalization of 'Data.SBV.Control.getUninterpretedValue'
 getUninterpretedValue :: (MonadIO m, MonadQuery m, HasKind a) => SBV a -> m String
 getUninterpretedValue s =
@@ -511,24 +889,74 @@
                                                                     Nothing -> bad r Nothing
                            _                                   -> bad r Nothing
 
+-- | "Make up" a CV for this type. Like zero, but smarter.
+defaultKindedValue :: Kind -> Maybe CV
+defaultKindedValue k = CV k <$> cvt k
+  where cvt :: Kind -> Maybe CVal
+        cvt KBool                 = Just $ CInteger 0
+        cvt KBounded{}            = Just $ CInteger 0
+        cvt KUnbounded            = Just $ CInteger 0
+        cvt KReal                 = Just $ CAlgReal 0
+        cvt (KUninterpreted _ ui) = uninterp ui
+        cvt KFloat                = Just $ CFloat 0
+        cvt KDouble               = Just $ CDouble 0
+        cvt KChar                 = Just $ CChar '\NUL'                -- why not?
+        cvt KString               = Just $ CString ""
+        cvt (KList  _)            = Just $ CList []
+        cvt (KSet  _)             = Just $ CSet $ RegularSet Set.empty -- why not? Arguably, could be the universal set
+        cvt (KTuple ks)           = CTuple <$> mapM cvt ks
+        cvt (KMaybe _)            = Just $ CMaybe Nothing
+        cvt (KEither k1 _)        = CEither . Left <$> cvt k1          -- why not?
+
+        -- Tricky case of uninterpreted
+        uninterp (Right (c:_)) = Just $ CUserSort (Just 1, c)
+        uninterp (Right [])    = Nothing                       -- I don't think this can actually happen, but just in case
+        uninterp (Left _)      = Nothing                       -- Out of luck, truly uninterpreted; we don't even know if it's inhabited.
+
 -- | Recover a given solver-printed value with a possible interpretation
 recoverKindedValue :: Kind -> SExpr -> Maybe CV
-recoverKindedValue k e = case e of
-                           ENum    i | isIntegralLike    -> Just $ mkConstCV k (fst i)
-                           ENum    i | isChar          k -> Just $ CV KChar    (CChar    (chr (fromIntegral (fst i))))
-                           EReal   i | isReal          k -> Just $ CV KReal    (CAlgReal i)
-                           EFloat  i | isFloat         k -> Just $ CV KFloat   (CFloat   i)
-                           EDouble i | isDouble        k -> Just $ CV KDouble  (CDouble  i)
-                           ECon    s | isString        k -> Just $ CV KString  (CString   (interpretString s))
-                           ECon    s | isUninterpreted k -> Just $ CV k        (CUserSort (getUIIndex k s, s))
-                           _         | isList          k -> Just $ CV k        (CList     (interpretList e))
-                           _         | isTuple         k -> Just $ CV k        (CTuple    (interpretTuple e))
+recoverKindedValue k e = case k of
+                           KBool            | ENum (i, _) <- e -> Just $ mkConstCV k i
+                                            | True             -> Nothing
 
-                           _ -> Nothing
+                           KBounded{}       | ENum (i, _) <- e -> Just $ mkConstCV k i
+                                            | True             -> Nothing
 
-  where isIntegralLike = or [f k | f <- [isBoolean, isBounded, isInteger, isReal, isFloat, isDouble]]
+                           KUnbounded       | ENum (i, _) <- e -> Just $ mkConstCV k i
+                                            | True             -> Nothing
 
-        getUIIndex (KUninterpreted  _ (Right xs)) i = i `elemIndex` xs
+                           KReal            | ENum (i, _) <- e -> Just $ mkConstCV k i
+                                            | EReal i     <- e -> Just $ CV KReal (CAlgReal i)
+                                            | True             -> Nothing
+
+                           KUninterpreted{} | ECon s <- e -> Just $ CV k $ CUserSort (getUIIndex k s, s)
+                                            | True             -> Nothing
+
+                           KFloat           | ENum (i, _) <- e -> Just $ mkConstCV k i
+                                            | EFloat i    <- e -> Just $ CV KFloat (CFloat i)
+                                            | True             -> Nothing
+
+                           KDouble          | ENum (i, _) <- e -> Just $ mkConstCV k i
+                                            | EDouble i   <- e -> Just $ CV KDouble (CDouble i)
+                                            | True             -> Nothing
+
+                           KChar            | ENum (i, _) <- e -> Just $ CV KChar $ CChar $ chr $ fromIntegral i
+                                            | True             -> Nothing
+
+                           KString          | ECon s      <- e -> Just $ CV KString $ CString $ interpretString s
+                                            | True             -> Nothing
+
+                           KList ek                            -> Just $ CV k $ CList $ interpretList ek e
+
+                           KSet ek                             -> Just $ CV k $ CSet $ interpretSet ek e
+
+                           KTuple{}                            -> Just $ CV k $ CTuple $ interpretTuple e
+
+                           KMaybe{}                            -> Just $ CV k $ CMaybe $ interpretMaybe k e
+
+                           KEither{}                           -> Just $ CV k $ CEither $ interpretEither k e
+
+  where getUIIndex (KUninterpreted  _ (Right xs)) i = i `elemIndex` xs
         getUIIndex _                              _ = Nothing
 
         stringLike xs = length xs >= 2 && head xs == '"' && last xs == '"'
@@ -544,10 +972,10 @@
         isStringSequence _                      = False
 
         -- Lists are tricky since z3 prints the 8-bit variants as strings. See: <http://github.com/Z3Prover/z3/issues/1808>
-        interpretList (ECon s)
+        interpretList _ (ECon s)
           | isStringSequence k && stringLike s
           = map (CInteger . fromIntegral . ord) $ interpretString s
-        interpretList topExpr = walk topExpr
+        interpretList ek topExpr = walk topExpr
           where walk (EApp [ECon "as", ECon "seq.empty", _]) = []
                 walk (EApp [ECon "seq.unit", v])             = case recoverKindedValue ek v of
                                                                  Just w -> [cvVal w]
@@ -559,10 +987,47 @@
                           | True          = "\nWhile parsing: " ++ t
                           where t = show topExpr
 
-                ek = case k of
-                       KList ik -> ik
-                       _        -> error $ "Impossible: Expected a sequence kind, but got: " ++ show k
+        -- Essentially treat sets as functions, since we do allow for store associations
+        interpretSet ke setExpr
+             | isUniversal setExpr             = ComplementSet Set.empty
+             | isEmpty     setExpr             = RegularSet    Set.empty
+             | Just (Right assocs) <- mbAssocs = decode assocs
+             | True                            = tbd "Expected a set value, but couldn't decipher the solver output."
 
+           where tbd w = error $ unlines [ ""
+                                         , "*** Data.SBV.interpretSet: Unable to process solver output."
+                                         , "***"
+                                         , "*** Kind    : " ++ show (KSet ke)
+                                         , "*** Received: " ++ show setExpr
+                                         , "*** Reason  : " ++ w
+                                         , "***"
+                                         , "*** This is either a bug or something SBV currently does not support."
+                                         , "*** Please report this as a feature request!"
+                                         ]
+
+
+                 isTrue (ENum (1, Nothing)) = True
+                 isTrue (ENum (0, Nothing)) = False
+                 isTrue bad                 = tbd $ "Non-boolean membership value seen: " ++ show bad
+
+                 isUniversal (EApp [EApp [ECon "as", ECon "const", EApp [ECon "Array", _, ECon "Bool"]], r]) = isTrue r
+                 isUniversal _                                                                               = False
+
+                 isEmpty     (EApp [EApp [ECon "as", ECon "const", EApp [ECon "Array", _, ECon "Bool"]], r]) = not $ isTrue r
+                 isEmpty     _                                                                               = False
+
+                 mbAssocs = parseSExprFunction setExpr
+
+                 decode (args, r) | isTrue r = ComplementSet $ Set.fromList [x | (x, False) <- map contents args]  -- deletions from universal
+                                  | True     = RegularSet    $ Set.fromList [x | (x, True)  <- map contents args]  -- additions to empty
+
+                 contents ([v], r) = (element v, isTrue r)
+                 contents bad      = tbd $ "Multi-valued set member seen: " ++ show bad
+
+                 element x = case recoverKindedValue ke x of
+                               Just v  -> cvVal v
+                               Nothing -> tbd $ "Unexpected value for kind: " ++ show (x, ke)
+
         interpretTuple te = walk (1 :: Int) (zipWith recoverKindedValue ks args) []
                 where (ks, n) = case k of
                                   KTuple eks -> (eks, length eks)
@@ -579,6 +1044,41 @@
                                                                   , "Expr: " ++ show te
                                                                   ]
 
+        -- SMaybe
+        interpretMaybe (KMaybe _)  (ECon "nothing_SBVMaybe")        = Nothing
+        interpretMaybe (KMaybe ek) (EApp [ECon "just_SBVMaybe", a]) = case recoverKindedValue ek a of
+                                                                        Just (CV _ v) -> Just v
+                                                                        Nothing       -> error $ unlines [ "Couldn't parse a maybe just value"
+                                                                                                         , "Kind: " ++ show ek
+                                                                                                         , "Expr: " ++ show a
+                                                                                                         ]
+        -- CVC4 puts in full ascriptions, handle those:
+        interpretMaybe _  (      EApp [ECon "as", ECon "nothing_SBVMaybe", _])     = Nothing
+        interpretMaybe mk (EApp [EApp [ECon "as", ECon "just_SBVMaybe",    _], a]) = interpretMaybe mk (EApp [ECon "just_SBVMaybe", a])
+
+        interpretMaybe _  other = error $ "Expected an SMaybe sexpr, but received: " ++ show (k, other)
+
+        -- SEither
+        interpretEither (KEither k1 _) (EApp [ECon "left_SBVEither",  a]) = case recoverKindedValue k1 a of
+                                                                              Just (CV _ v) -> Left v
+                                                                              Nothing       -> error $ unlines [ "Couldn't parse an either value on the left"
+                                                                                                               , "Kind: " ++ show k1
+                                                                                                               , "Expr: " ++ show a
+                                                                                                               ]
+        interpretEither (KEither _ k2) (EApp [ECon "right_SBVEither", b]) = case recoverKindedValue k2 b of
+                                                                              Just (CV _ v) -> Right v
+                                                                              Nothing       -> error $ unlines [ "Couldn't parse an either value on the right"
+                                                                                                               , "Kind: " ++ show k2
+                                                                                                               , "Expr: " ++ show b
+                                                                                                               ]
+
+        -- CVC4 puts full ascriptions:
+        interpretEither ek (EApp [EApp [ECon "as", ECon "left_SBVEither",  _], a]) = interpretEither ek (EApp [ECon "left_SBVEither", a])
+        interpretEither ek (EApp [EApp [ECon "as", ECon "right_SBVEither", _], b]) = interpretEither ek (EApp [ECon "right_SBVEither", b])
+
+        interpretEither _ other = error $ "Expected an SEither sexpr, but received: " ++ show (k, other)
+
+
 -- | Generalization of 'Data.SBV.Control.getValueCV'
 getValueCV :: (MonadIO m, MonadQuery m) => Maybe Int -> SV -> m CV
 getValueCV mbi s
@@ -600,6 +1100,52 @@
                     (CV KReal (CAlgReal a), CV KReal (CAlgReal b)) -> return $ CV KReal (CAlgReal (mergeAlgReals ("Cannot merge real-values for " ++ show s) a b))
                     _                                              -> bad
 
+-- | Generalization of 'Data.SBV.Control.getUIFunCVAssoc'
+getUIFunCVAssoc :: forall m. (MonadIO m, MonadQuery m) => Maybe Int -> (String, SBVType) -> m ([([CV], CV)], CV)
+getUIFunCVAssoc mbi (nm, typ) = do
+  let modelIndex = case mbi of
+                     Nothing -> ""
+                     Just i  -> " :model_index " ++ show i
+
+      cmd        = "(get-value (" ++ nm ++ ")" ++ modelIndex ++ ")"
+
+      bad        = unexpected "get-value" cmd "a function value" Nothing
+
+  r <- ask cmd
+
+  let (ats, rt) = case typ of
+                    SBVType as | length as > 1 -> (init as, last as)
+                    _                          -> error $ "Data.SBV.getUIFunCVAssoc: Expected a function type, got: " ++ show typ
+
+  let convert (vs, d) = (,) <$> mapM toPoint vs <*> toRes d
+      toPoint (as, v)
+         | length as == length ats = (,) <$> zipWithM recoverKindedValue ats as <*> toRes v
+         | True                    = error $ "Data.SBV.getUIFunCVAssoc: Mismatching type/value arity, got: " ++ show (as, ats)
+
+      toRes :: SExpr -> Maybe CV
+      toRes = recoverKindedValue rt
+
+      -- In case we end up in the pointwise scenerio, boolify the result
+      -- as that's the only type we support here.
+      tryPointWise bailOut = do mbSExprs <- pointWiseExtract nm typ
+                                case mbSExprs of
+                                  Nothing     -> bailOut
+                                  Just sExprs -> case convert sExprs of
+                                                   Just res -> return res
+                                                   Nothing  -> bailOut
+
+  parse r bad $ \case EApp [EApp [ECon o, e]] | o == nm -> let bailOut = bad r Nothing
+                                                           in case parseSExprFunction e of
+                                                                Just (Right assocs) | Just res <- convert assocs                   -> return res
+                                                                                    | True                                         -> tryPointWise bailOut
+
+                                                                Just (Left nm')     | nm == nm', Just res <- defaultKindedValue rt -> return ([], res)
+                                                                                    | True                                         -> bad r Nothing
+
+                                                                Nothing                                                            -> tryPointWise bailOut
+
+                      _                                 -> bad r Nothing
+
 -- | Generalization of 'Data.SBV.Control.checkSat'
 checkSat :: (MonadIO m, MonadQuery m) => m CheckSatResult
 checkSat = do cfg <- getConfig
@@ -647,28 +1193,69 @@
 
                     walk rObs []
 
+-- | Get UIs, both constants and functions. This call returns both the before and after query ones.
+-- | Generalization of 'Data.SBV.Control.getUIs'.
+getUIs :: forall m. (MonadIO m, MonadQuery m) => m [(String, SBVType)]
+getUIs = do State{rUIMap, rIncState} <- queryState
+            prior <- io $ readIORef rUIMap
+            new   <- io $ readIORef rIncState >>= readIORef . rNewUIs
+            return $ nub $ sort $ Map.toList prior ++ Map.toList new
+
 -- | Repeatedly issue check-sat, after refuting the previous model.
 -- The bool is true if the model is unique upto prefix existentials.
-getAllSatResult :: forall m. (MonadIO m, MonadQuery m, SolverContext m) => m (Bool, Bool, [SMTResult])
+getAllSatResult :: forall m. (MonadIO m, MonadQuery m, SolverContext m) => m (Bool, Bool, Bool, [SMTResult])
 getAllSatResult = do queryDebug ["*** Checking Satisfiability, all solutions.."]
 
                      cfg <- getConfig
 
-                     State{rUsedKinds} <- queryState
+                     topState@State{rUsedKinds} <- queryState
 
                      ki    <- liftIO $ readIORef rUsedKinds
                      qinps <- getQuantifiedInputs
 
-                     let usorts = [s | us@(KUninterpreted s _) <- Set.toList ki, isFree us]
+                     allUninterpreteds <- getUIs
 
+                      -- Functions have at least two kinds in their type and all components must be "interpreted"
+                     let allUiFuns = [u | satTrackUFs cfg                                         -- config says consider UIFs
+                                        , u@(nm, SBVType as) <- allUninterpreteds, length as > 1  -- get the function ones
+                                        , not (isNonModelVar cfg nm)                              -- make sure they aren't explicitly ignored
+                                     ]
+
+                         -- We can only "allSat" if all component types themselves are interpreted. (Otherwise
+                         -- there is no way to reflect back the values to the solver.)
+                         collectAcceptable []                              sofar = return sofar
+                         collectAcceptable ((nm, t@(SBVType ats)):rest) sofar
+                           | not (any hasUninterpretedSorts ats)
+                           = collectAcceptable rest (nm : sofar)
+                           | True
+                           = do queryDebug [ "*** SBV.allSat: Uninterpreted function: " ++ nm ++ " :: " ++ show t
+                                           , "*** Will *not* be used in allSat consideretions since its type"
+                                           , "*** has uninterpreted sorts present."
+                                           ]
+                                collectAcceptable rest sofar
+
+                     uiFuns <- reverse <$> collectAcceptable allUiFuns []
+
+                     -- If there are uninterpreted functions, arrange so that z3's pretty-printer flattens things out
+                     -- as cex's tend to get larger
+                     unless (null uiFuns) $
+                        let solverCaps = capabilities (solver cfg)
+                        in case supportsFlattenedModels solverCaps of
+                             Nothing   -> return ()
+                             Just cmds -> mapM_ (send True) cmds
+
+                     let usorts = [s | us@(KUninterpreted s _) <- Set.toAscList ki, isFree us]
+
                      unless (null usorts) $ queryDebug [ "*** SBV.allSat: Uninterpreted sorts present: " ++ unwords usorts
                                                        , "***             SBV will use equivalence classes to generate all-satisfying instances."
                                                        ]
 
-                     let vars :: [(SVal, NamedSymVar)]
-                         vars = let allModelInputs = takeWhile ((/= ALL) . fst) qinps
+                     let allModelInputs  = takeWhile ((/= ALL) . fst) qinps
+                         -- Add on observables only if we're not in a quantified context:
+                         grabObservables = length allModelInputs == length qinps -- i.e., we didn't drop anything
 
-                                    sortByNodeId :: [NamedSymVar] -> [NamedSymVar]
+                         vars :: [(SVal, NamedSymVar)]
+                         vars = let sortByNodeId :: [NamedSymVar] -> [NamedSymVar]
                                     sortByNodeId = sortBy (compare `on` (\(SV _ n, _) -> n))
 
                                     mkSVal :: NamedSymVar -> (SVal, NamedSymVar)
@@ -679,35 +1266,71 @@
                          -- If we have any universals, then the solutions are unique upto prefix existentials.
                          w = ALL `elem` map fst qinps
 
-                     (sc, ms) <- loop vars cfg
-                     return (sc, w, reverse ms)
+                     (sc, unk, ms) <- loop grabObservables topState (allUiFuns, uiFuns) qinps vars cfg
+                     return (sc, w, unk, reverse ms)
 
    where isFree (KUninterpreted _ (Left _)) = True
          isFree _                           = False
 
-         loop vars cfg = go (1::Int) []
-           where go :: Int -> [SMTResult] -> m (Bool, [SMTResult])
+         loop grabObservables topState (allUiFuns, uiFunsToReject) qinps vars cfg = go (1::Int) []
+           where go :: Int -> [SMTResult] -> m (Bool, Bool, [SMTResult])
                  go !cnt sofar
                    | Just maxModels <- allSatMaxModelCount cfg, cnt > maxModels
                    = do queryDebug ["*** Maximum model count request of " ++ show maxModels ++ " reached, stopping the search."]
-                        return (True, sofar)
+
+                        when (allSatPrintAlong cfg) $ io $ putStrLn "Search stopped since model count request was reached."
+
+                        return (True, False, sofar)
                    | True
                    = do queryDebug ["Looking for solution " ++ show cnt]
+
+                        let endMsg = when (allSatPrintAlong cfg && not (null sofar)) $ do
+                                             let msg 0 = "No solutions found."
+                                                 msg 1 = "This is the only solution."
+                                                 msg n = "Found " ++ show n ++ " different solutions."
+                                             io . putStrLn $ msg (cnt - 1)
+
                         cs <- checkSat
+
                         case cs of
-                          Unsat -> return (False, sofar)
+                          Unsat -> do endMsg
+                                      return (False, False, sofar)
+
                           Unk   -> do queryDebug ["*** Solver returned unknown, terminating query."]
-                                      return (False, sofar)
+                                      endMsg
+                                      return (False, True, sofar)
+
                           Sat   -> do assocs <- mapM (\(sval, (sv, n)) -> do cv <- getValueCV Nothing sv
-                                                                             return (n, (sval, cv))) vars
+                                                                             return (sv, (n, (sval, cv)))) vars
 
-                                      let m = Satisfiable cfg SMTModel { modelObjectives = []
-                                                                       , modelAssocs     = [(n, cv) | (n, (_, cv)) <- assocs]
-                                                                       }
+                                      let getUIFun ui@(nm, t) = do cvs <- getUIFunCVAssoc Nothing ui
+                                                                   return (nm, (t, cvs))
+                                      uiFunVals <- mapM getUIFun allUiFuns
 
-                                          (interpreteds, uninterpreteds) = partition (not . isFree . kindOf . fst) (map snd assocs)
+                                      -- Add on observables if we're asked to do so:
+                                      obsvs <- if grabObservables
+                                                  then getObservables
+                                                  else return []
 
-                                          -- For each "interpreted" variable, figure out the model equivalence
+                                      bindings <- let grab i@(ALL, _)      = return (i, Nothing)
+                                                      grab i@(EX, (sv, _)) = case sv `lookup` assocs of
+                                                                               Just (_, (_, cv)) -> return (i, Just cv)
+                                                                               Nothing           -> do cv <- getValueCV Nothing sv
+                                                                                                       return (i, Just cv)
+                                                  in if validateModel cfg
+                                                        then Just <$> mapM grab qinps
+                                                        else return Nothing
+
+                                      let model = SMTModel { modelObjectives = []
+                                                           , modelBindings   = bindings
+                                                           , modelAssocs     = sortOn fst obsvs ++ [(n, cv) | (_, (n, (_, cv))) <- assocs]
+                                                           , modelUIFuns     = uiFunVals
+                                                           }
+                                          m = Satisfiable cfg model
+
+                                          (interpreteds, uninterpreteds) = partition (not . isFree . kindOf . fst) (map (snd . snd) assocs)
+
+                                          -- For each interpreted variable, figure out the model equivalence
                                           -- NB. When the kind is floating, we *have* to be careful, since +/- zero, and NaN's
                                           -- and equality don't get along!
                                           interpretedEqs :: [SVal]
@@ -717,11 +1340,11 @@
                                                     | True                    = a `svNotEqual` b
 
                                                    fpNotEq a b = SVal KBool $ Right $ cache r
-                                                       where r st = do swa <- svToSV st a
-                                                                       swb <- svToSV st b
-                                                                       newExpr st KBool (SBVApp (IEEEFP FP_ObjEqual) [swa, swb])
+                                                       where r st = do sva <- svToSV st a
+                                                                       svb <- svToSV st b
+                                                                       newExpr st KBool (SBVApp (IEEEFP FP_ObjEqual) [sva, svb])
 
-                                          -- For each "uninterpreted" variable, use equivalence class
+                                          -- For each uninterpreted constant, use equivalence class
                                           uninterpretedEqs :: [SVal]
                                           uninterpretedEqs = concatMap pwDistinct         -- Assert that they are pairwise distinct
                                                            . filter (\l -> length l > 1)  -- Only need this class if it has at least two members
@@ -732,20 +1355,104 @@
                                             where pwDistinct :: [SVal] -> [SVal]
                                                   pwDistinct ss = [x `svNotEqual` y | (x:ys) <- tails ss, y <- ys]
 
+                                          -- For each uninterpreted function, create a disqualifying equation
+                                          -- We do this rather brute-force, since we need to create a new function
+                                          -- and do an existential assertion.
+                                          uninterpretedReject :: Maybe [String]
+                                          uninterpretedFuns    :: [String]
+                                          (uninterpretedReject, uninterpretedFuns) = (uiReject, concat defs)
+                                              where uiReject = case rejects of
+                                                                 []  -> Nothing
+                                                                 xs  -> Just xs
+
+                                                    (rejects, defs) = unzip [mkNotEq ui | ui@(nm, _) <- uiFunVals, nm `elem` uiFunsToReject]
+
+                                                    -- Otherwise, we have things to refute, go for it:
+                                                    mkNotEq (nm, (SBVType ts, vs)) = (reject, def ++ dif)
+                                                      where nm' = nm ++ "_model" ++ show cnt
+
+                                                            reject = nm' ++ "_reject"
+
+                                                            -- rounding mode doesn't matter here, just pick one
+                                                            scv = cvToSMTLib RoundNearestTiesToEven
+
+                                                            (ats, rt) = (init ts, last ts)
+
+                                                            args = unwords ["(x!" ++ show i ++ " " ++ smtType t ++ ")" | (t, i) <- zip ats [(0::Int)..]]
+                                                            res  = smtType rt
+
+                                                            params = ["x!" ++ show i | (_, i) <- zip ats [(0::Int)..]]
+
+                                                            uparams = unwords params
+
+                                                            chain (vals, fallThru) = walk vals
+                                                              where walk []               = ["   " ++ scv fallThru ++ replicate (length vals) ')']
+                                                                    walk ((as, r) : rest) = ("   (ite " ++ cond as ++ " " ++ scv r ++ "") :  walk rest
+
+                                                                    cond as = "(and " ++ unwords (zipWith eq params as) ++ ")"
+                                                                    eq p a  = "(= " ++ p ++ " " ++ scv a ++ ")"
+
+                                                            def =    ("(define-fun " ++ nm' ++ " (" ++ args ++ ") " ++ res)
+                                                                  :  chain vs
+                                                                  ++ [")"]
+
+                                                            pad = replicate (1 + length nm' - length nm) ' '
+
+                                                            dif = [ "(define-fun " ++  reject ++ " () Bool"
+                                                                  , "   (exists (" ++ args ++ ")"
+                                                                  , "           (distinct (" ++ nm  ++ pad ++ uparams ++ ")"
+                                                                  , "                     (" ++ nm' ++ " " ++ uparams ++ "))))"
+                                                                  ]
+
                                           eqs = interpretedEqs ++ uninterpretedEqs
+
                                           disallow = case eqs of
                                                        [] -> Nothing
                                                        _  -> Just $ SBV $ foldr1 svOr eqs
 
+                                      when (allSatPrintAlong cfg) $ do
+                                        io $ putStrLn $ "Solution #" ++ show cnt ++ ":"
+                                        io $ putStrLn $ showModel cfg model
+
                                       let resultsSoFar = m : sofar
 
-                                      -- make sure there's some var. This happens! 'allSat true' is the pathetic example.
+                                          -- This is clunky, but let's not generate a rejector unless we really need it
+                                          needMoreIterations
+                                                | Just maxModels <- allSatMaxModelCount cfg, (cnt+1) > maxModels = False
+                                                | True                                                           = True
 
-                                      case disallow of
-                                        Nothing -> return (False, resultsSoFar)
-                                        Just d  -> do constrain d
-                                                      go (cnt+1) resultsSoFar
+                                      -- Send function disequalities, if any:
+                                      if not needMoreIterations
+                                         then go (cnt+1) resultsSoFar
+                                         else do let uiFunRejector   = "uiFunRejector_model_" ++ show cnt
+                                                     header          = "define-fun " ++ uiFunRejector ++ " () Bool "
 
+                                                     defineRejector []     = return ()
+                                                     defineRejector [x]    = send True $ "(" ++ header ++ x ++ ")"
+                                                     defineRejector (x:xs) = mapM_ (send True) $ mergeSExpr $  ("(" ++ header)
+                                                                                                            :  ("        (or " ++ x)
+                                                                                                            :  ["            " ++ e | e <- xs]
+                                                                                                            ++ ["        ))"]
+                                                 rejectFuncs <- case uninterpretedReject of
+                                                                  Nothing -> return Nothing
+                                                                  Just fs -> do mapM_ (send True) $ mergeSExpr uninterpretedFuns
+                                                                                defineRejector fs
+                                                                                return $ Just uiFunRejector
+
+                                                 -- send the disallow clause and the uninterpreted rejector:
+                                                 case (disallow, rejectFuncs) of
+                                                    (Nothing, Nothing) -> return (False, False, resultsSoFar)
+                                                    (Just d,  Nothing) -> do constrain d
+                                                                             go (cnt+1) resultsSoFar
+                                                    (Nothing, Just f)  -> do send True $ "(assert " ++ f ++ ")"
+                                                                             go (cnt+1) resultsSoFar
+                                                    (Just d,  Just f)  -> -- This is where it gets ugly. We have an SBV and a string and we need to "or" them.
+                                                                          -- But we need a way to force 'd' to be produced. So, go ahead and force it:
+                                                                          do constrain $ d .=> d  -- NB: Redundant, but it makes sure the corresponding constraint gets shown
+                                                                             svd <- io $ svToSV topState (unSBV d)
+                                                                             send True $ "(assert (or " ++ f ++ " " ++ show svd ++ "))"
+                                                                             go (cnt+1) resultsSoFar
+
 -- | Generalization of 'Data.SBV.Control.getUnsatAssumptions'
 getUnsatAssumptions :: (MonadIO m, MonadQuery m) => [String] -> [(String, a)] -> m [a]
 getUnsatAssumptions originals proxyMap = do
@@ -824,8 +1531,8 @@
 runProofOn :: SBVRunMode -> QueryContext -> [String] -> Result -> SMTProblem
 runProofOn rm context comments res@(Result ki _qcInfo _observables _codeSegs is consts tbls arrs uis axs pgm cstrs _assertions outputs) =
      let (config, isSat, isSafe, isSetup) = case rm of
-                                              SMTMode stage s c -> (c, s, isSafetyCheckingIStage stage, isSetupIStage stage)
-                                              _                 -> error $ "runProofOn: Unexpected run mode: " ++ show rm
+                                              SMTMode _ stage s c -> (c, s, isSafetyCheckingIStage stage, isSetupIStage stage)
+                                              _                   -> error $ "runProofOn: Unexpected run mode: " ++ show rm
 
          flipQ (ALL, x) = (EX,  x)
          flipQ (EX,  x) = (ALL, x)
@@ -860,6 +1567,12 @@
      st <- symbolicEnv
      rm <- liftIO $ readIORef (runMode st)
 
+     -- Make sure the phases match:
+     () <- liftIO $ case (queryContext, rm) of
+                      (QueryInternal, _)                                -> return ()  -- no worries, internal
+                      (QueryExternal, SMTMode QueryExternal ISetup _ _) -> return () -- legitimate runSMT call
+                      _                                                 -> invalidQuery rm
+
      -- If we're doing an external query, then we cannot allow quantifiers to be present. Why?
      -- Consider:
      --
@@ -884,8 +1597,17 @@
      --
      -- So, we check if this is an external-query, and if there are quantified variables. If so, we
      -- cowardly refuse to continue. For details, see: <http://github.com/LeventErkok/sbv/issues/407>
+     --
+     -- However, as discussed in <https://github.com/LeventErkok/sbv/issues/459>, we'll allow for this
+     -- if the user explicitly asks as to do so. In that case, all bets are off!
 
-     () <- liftIO $ case queryContext of
+     let allowQQs = case rm of
+                      SMTMode _ _ _ cfg -> allowQuantifiedQueries cfg
+                      CodeGen           -> False -- doesn't matter in these two
+                      Concrete{}        -> False -- cases, but we're being careful
+
+     () <- unless allowQQs $ liftIO $
+                    case queryContext of
                       QueryInternal -> return ()         -- we're good, internal usages don't mess with scopes
                       QueryExternal -> do
                         (userInps, _) <- readIORef (rinps st)
@@ -909,7 +1631,7 @@
 
      case rm of
         -- Transitioning from setup
-        SMTMode stage isSAT cfg | not (isRunIStage stage) -> do
+        SMTMode qc stage isSAT cfg | not (isRunIStage stage) -> do
 
                                                 let backend = engine (solver cfg)
 
@@ -920,10 +1642,9 @@
                                                     cfg' = cfg { solverSetOptions = solverSetOptions cfg ++ setOpts }
                                                     pgm  = smtLibPgm cfg'
 
-                                                liftIO $ writeIORef (runMode st) $ SMTMode IRun isSAT cfg
+                                                liftIO $ writeIORef (runMode st) $ SMTMode qc IRun isSAT cfg
 
-                                                lift $ join $ liftIO $ backend cfg' st (show pgm) $
-                                                    extractIO . runReaderT userQuery
+                                                lift $ join $ liftIO $ backend cfg' st (show pgm) $ extractIO . runReaderT userQuery
 
         -- Already in a query, in theory we can just continue, but that causes use-case issues
         -- so we reject it. TODO: Review if we should actually support this. The issue arises with
@@ -959,26 +1680,29 @@
         --
         -- So, we just reject it.
 
-        SMTMode IRun _ _ -> error $ unlines [ ""
-                                            , "*** Data.SBV: Unsupported nested query is detected."
-                                            , "***"
-                                            , "*** Please group your queries into one block. Note that this"
-                                            , "*** can also arise if you have a call to 'query' not within 'runSMT'"
-                                            , "*** For instance, within 'sat'/'prove' calls with custom user queries."
-                                            , "*** The solution is to do the sat/prove part in the query directly."
-                                            , "***"
-                                            , "*** While multiple/nested queries should not be necessary in general,"
-                                            , "*** please do get in touch if your use case does require such a feature,"
-                                            , "*** to see how we can accommodate such scenarios."
-                                            ]
+        SMTMode _ IRun _ _ -> error $ unlines [ ""
+                                              , "*** Data.SBV: Unsupported nested query is detected."
+                                              , "***"
+                                              , "*** Please group your queries into one block. Note that this"
+                                              , "*** can also arise if you have a call to 'query' not within 'runSMT'"
+                                              , "*** For instance, within 'sat'/'prove' calls with custom user queries."
+                                              , "*** The solution is to do the sat/prove part in the query directly."
+                                              , "***"
+                                              , "*** While multiple/nested queries should not be necessary in general,"
+                                              , "*** please do get in touch if your use case does require such a feature,"
+                                              , "*** to see how we can accommodate such scenarios."
+                                              ]
 
         -- Otherwise choke!
-        m -> error $ unlines [ ""
-                             , "*** Data.SBV: Invalid query call."
-                             , "***"
-                             , "***   Current mode: " ++ show m
-                             , "***"
-                             , "*** Query calls are only valid within runSMT/runSMTWith calls"
-                             ]
+        _ -> invalidQuery rm
 
-{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
+  where invalidQuery rm = error $ unlines [ ""
+                                          , "*** Data.SBV: Invalid query call."
+                                          , "***"
+                                          , "***   Current mode: " ++ show rm
+                                          , "***"
+                                          , "*** Query calls are only valid within runSMT/runSMTWith calls"
+                                          ]
+
+{-# ANN module          ("HLint: ignore Reduce duplication" :: String) #-}
+{-# ANN getAllSatResult ("HLint: ignore Use forM_"          :: String) #-}
diff --git a/Data/SBV/Core/AlgReals.hs b/Data/SBV/Core/AlgReals.hs
--- a/Data/SBV/Core/AlgReals.hs
+++ b/Data/SBV/Core/AlgReals.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.AlgReals
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,8 +9,7 @@
 -- Algrebraic reals in Haskell.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
 
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
diff --git a/Data/SBV/Core/Concrete.hs b/Data/SBV/Core/Concrete.hs
--- a/Data/SBV/Core/Concrete.hs
+++ b/Data/SBV/Core/Concrete.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.Concrete
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,6 +9,9 @@
 -- Operations on concrete values
 -----------------------------------------------------------------------------
 
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
 module Data.SBV.Core.Concrete
   ( module Data.SBV.Core.Concrete
   ) where
@@ -24,30 +27,73 @@
 import Data.SBV.Core.Kind
 import Data.SBV.Core.AlgReals
 
+import Data.Proxy
+
 import Data.SBV.Utils.Numeric (fpIsEqualObjectH, fpCompareObjectH)
 
+import Data.Set (Set)
+import qualified Data.Set as Set
+
+-- | A 'RCSet' is either a regular set or a set given by its complement from the corresponding universal set.
+data RCSet a = RegularSet    (Set a)
+             | ComplementSet (Set a)
+
+-- | Show instance. Regular sets are shown as usual.
+-- Complements are shown "U -" notation.
+instance Show a => Show (RCSet a) where
+  show rcs = case rcs of
+               ComplementSet s | Set.null s -> "U"
+                               | True       -> "U - " ++ sh (Set.toAscList s)
+               RegularSet    s              ->           sh (Set.toAscList s)
+   where sh xs = '{' : intercalate "," (map show xs) ++ "}"
+
+-- | Structural equality for 'RCSet'. We need Eq/Ord instances for 'RCSet' because we want to put them in maps/tables. But
+-- we don't want to derive these, nor make it an instance! Why? Because the same set can have multiple representations if the underlying
+-- type is finite. For instance, @{True} = U - {False}@ for boolean sets! Instead, we use the following two functions,
+-- which are equivalent to Eq/Ord instances and work for our purposes, but we do not export these to the user.
+eqRCSet :: Eq a => RCSet a -> RCSet a -> Bool
+eqRCSet (RegularSet    a) (RegularSet    b) = a == b
+eqRCSet (ComplementSet a) (ComplementSet b) = a == b
+eqRCSet _                 _                 = False
+
+-- | Comparing 'RCSet' values. See comments for 'eqRCSet' on why we don't define the 'Ord' instance.
+compareRCSet :: Ord a => RCSet a -> RCSet a -> Ordering
+compareRCSet (RegularSet    a) (RegularSet    b) = a `compare` b
+compareRCSet (RegularSet    _) (ComplementSet _) = LT
+compareRCSet (ComplementSet _) (RegularSet    _) = GT
+compareRCSet (ComplementSet a) (ComplementSet b) = a `compare` b
+
+instance HasKind a => HasKind (RCSet a) where
+  kindOf _ = KSet (kindOf (Proxy @a))
+
 -- | A constant value
-data CVal = CAlgReal  !AlgReal             -- ^ algebraic real
-          | CInteger  !Integer             -- ^ bit-vector/unbounded integer
-          | CFloat    !Float               -- ^ float
-          | CDouble   !Double              -- ^ double
-          | CChar     !Char                -- ^ character
-          | CString   !String              -- ^ string
-          | CList     ![CVal]              -- ^ list
-          | CUserSort !(Maybe Int, String) -- ^ value of an uninterpreted/user kind. The Maybe Int shows index position for enumerations
-          | CTuple    ![CVal]              -- ^ tuple
+data CVal = CAlgReal  !AlgReal              -- ^ Algebraic real
+          | CInteger  !Integer              -- ^ Bit-vector/unbounded integer
+          | CFloat    !Float                -- ^ Float
+          | CDouble   !Double               -- ^ Double
+          | CChar     !Char                 -- ^ Character
+          | CString   !String               -- ^ String
+          | CList     ![CVal]               -- ^ List
+          | CSet      !(RCSet CVal)         -- ^ Set. Can be regular or complemented.
+          | CUserSort !(Maybe Int, String)  -- ^ Value of an uninterpreted/user kind. The Maybe Int shows index position for enumerations
+          | CTuple    ![CVal]               -- ^ Tuple
+          | CMaybe    !(Maybe CVal)         -- ^ Maybe
+          | CEither   !(Either CVal CVal)   -- ^ Disjoint union
 
 -- | Assing a rank to constant values, this is structural and helps with ordering
 cvRank :: CVal -> Int
-cvRank CAlgReal  {} = 0
-cvRank CInteger  {} = 1
-cvRank CFloat    {} = 2
-cvRank CDouble   {} = 3
-cvRank CChar     {} = 4
-cvRank CString   {} = 5
-cvRank CList     {} = 6
-cvRank CUserSort {} = 7
-cvRank CTuple    {} = 8
+cvRank CAlgReal  {} =  0
+cvRank CInteger  {} =  1
+cvRank CFloat    {} =  2
+cvRank CDouble   {} =  3
+cvRank CChar     {} =  4
+cvRank CString   {} =  5
+cvRank CList     {} =  6
+cvRank CSet      {} =  7
+cvRank CUserSort {} =  8
+cvRank CTuple    {} =  9
+cvRank CMaybe    {} = 10
+cvRank CEither   {} = 11
 
 -- | Eq instance for CVVal. Note that we cannot simply derive Eq/Ord, since CVAlgReal doesn't have proper
 -- instances for these when values are infinitely precise reals. However, we do
@@ -60,9 +106,20 @@
   CChar     a == CChar     b = a == b
   CString   a == CString   b = a == b
   CList     a == CList     b = a == b
+  CSet      a == CSet      b = a `eqRCSet` b
   CUserSort a == CUserSort b = a == b
   CTuple    a == CTuple    b = a == b
-  _           == _           = False
+  CMaybe    a == CMaybe    b = a == b
+  CEither   a == CEither   b = a == b
+  a           == b           = if cvRank a == cvRank b
+                                  then error $ unlines [ ""
+                                                       , "*** Data.SBV.Eq.CVal: Impossible happened: same rank in comparison fallthru"
+                                                       , "***"
+                                                       , "***   Received: " ++ show (cvRank a, cvRank b)
+                                                       , "***"
+                                                       , "*** Please report this as a bug!"
+                                                       ]
+                                  else False
 
 -- | Ord instance for VWVal. Same comments as the 'Eq' instance why this cannot be derived.
 instance Ord CVal where
@@ -73,9 +130,22 @@
   CChar     a `compare` CChar b     = a        `compare`                  b
   CString   a `compare` CString b   = a        `compare`                  b
   CList     a `compare` CList   b   = a        `compare`                  b
+  CSet      a `compare` CSet    b   = a        `compareRCSet`             b
   CUserSort a `compare` CUserSort b = a        `compare`                  b
   CTuple    a `compare` CTuple    b = a        `compare`                  b
-  a           `compare` b           = cvRank a `compare`                  cvRank b
+  CMaybe    a `compare` CMaybe    b = a        `compare`                  b
+  CEither   a `compare` CEither   b = a        `compare`                  b
+  a           `compare` b           = let ra = cvRank a
+                                          rb = cvRank b
+                                      in if ra == rb
+                                            then error $ unlines [ ""
+                                                                 , "*** Data.SBV.Ord.CVal: Impossible happened: same rank in comparison fallthru"
+                                                                 , "***"
+                                                                 , "***   Received: " ++ show (ra, rb)
+                                                                 , "***"
+                                                                 , "*** Please report this as a bug!"
+                                                                 ]
+                                            else cvRank a `compare` cvRank b
 
 -- | 'CV' represents a concrete word of a fixed size:
 -- For signed words, the most significant digit is considered to be the sign.
@@ -186,33 +256,70 @@
 trueCV  = CV KBool (CInteger 1)
 
 -- | Lift a unary function through a 'CV'.
-liftCV :: (AlgReal -> b) -> (Integer -> b) -> (Float -> b) -> (Double -> b) -> (Char -> b) -> (String -> b) -> ((Maybe Int, String) -> b) -> ([CVal] -> b) -> ([CVal] -> b) -> CV -> b
-liftCV f _ _ _ _ _ _ _ _ (CV _ (CAlgReal  v)) = f v
-liftCV _ f _ _ _ _ _ _ _ (CV _ (CInteger  v)) = f v
-liftCV _ _ f _ _ _ _ _ _ (CV _ (CFloat    v)) = f v
-liftCV _ _ _ f _ _ _ _ _ (CV _ (CDouble   v)) = f v
-liftCV _ _ _ _ f _ _ _ _ (CV _ (CChar     v)) = f v
-liftCV _ _ _ _ _ f _ _ _ (CV _ (CString   v)) = f v
-liftCV _ _ _ _ _ _ f _ _ (CV _ (CUserSort v)) = f v
-liftCV _ _ _ _ _ _ _ f _ (CV _ (CList     v)) = f v
-liftCV _ _ _ _ _ _ _ _ f (CV _ (CTuple    v)) = f v
+liftCV :: (AlgReal             -> b)
+       -> (Integer             -> b)
+       -> (Float               -> b)
+       -> (Double              -> b)
+       -> (Char                -> b)
+       -> (String              -> b)
+       -> ((Maybe Int, String) -> b)
+       -> ([CVal]              -> b)
+       -> (RCSet CVal          -> b)
+       -> ([CVal]              -> b)
+       -> (Maybe CVal          -> b)
+       -> (Either CVal CVal    -> b)
+       -> CV
+       -> b
+liftCV f _ _ _ _ _ _ _ _ _ _ _ (CV _ (CAlgReal  v)) = f v
+liftCV _ f _ _ _ _ _ _ _ _ _ _ (CV _ (CInteger  v)) = f v
+liftCV _ _ f _ _ _ _ _ _ _ _ _ (CV _ (CFloat    v)) = f v
+liftCV _ _ _ f _ _ _ _ _ _ _ _ (CV _ (CDouble   v)) = f v
+liftCV _ _ _ _ f _ _ _ _ _ _ _ (CV _ (CChar     v)) = f v
+liftCV _ _ _ _ _ f _ _ _ _ _ _ (CV _ (CString   v)) = f v
+liftCV _ _ _ _ _ _ f _ _ _ _ _ (CV _ (CUserSort v)) = f v
+liftCV _ _ _ _ _ _ _ f _ _ _ _ (CV _ (CList     v)) = f v
+liftCV _ _ _ _ _ _ _ _ f _ _ _ (CV _ (CSet      v)) = f v
+liftCV _ _ _ _ _ _ _ _ _ f _ _ (CV _ (CTuple    v)) = f v
+liftCV _ _ _ _ _ _ _ _ _ _ f _ (CV _ (CMaybe    v)) = f v
+liftCV _ _ _ _ _ _ _ _ _ _ _ f (CV _ (CEither   v)) = f v
 
 -- | Lift a binary function through a 'CV'.
-liftCV2 :: (AlgReal -> AlgReal -> b) -> (Integer -> Integer -> b) -> (Float -> Float -> b) -> (Double -> Double -> b) -> (Char -> Char -> b) -> (String -> String -> b) -> ([CVal] -> [CVal] -> b) -> ([CVal] -> [CVal] -> b) -> ((Maybe Int, String) -> (Maybe Int, String) -> b) -> CV -> CV -> b
-liftCV2 r i f d c s u v w x y = case (cvVal x, cvVal y) of
-                                (CAlgReal  a, CAlgReal  b) -> r a b
-                                (CInteger  a, CInteger  b) -> i a b
-                                (CFloat    a, CFloat    b) -> f a b
-                                (CDouble   a, CDouble   b) -> d a b
-                                (CChar     a, CChar     b) -> c a b
-                                (CString   a, CString   b) -> s a b
-                                (CList     a, CList     b) -> u a b
-                                (CTuple    a, CTuple    b) -> v a b
-                                (CUserSort a, CUserSort b) -> w a b
-                                _                          -> error $ "SBV.liftCV2: impossible, incompatible args received: " ++ show (x, y)
+liftCV2 :: (AlgReal             -> AlgReal             -> b)
+        -> (Integer             -> Integer             -> b)
+        -> (Float               -> Float               -> b)
+        -> (Double              -> Double              -> b)
+        -> (Char                -> Char                -> b)
+        -> (String              -> String              -> b)
+        -> ([CVal]              -> [CVal]              -> b)
+        -> ([CVal]              -> [CVal]              -> b)
+        -> (Maybe CVal          -> Maybe CVal          -> b)
+        -> (Either CVal CVal    -> Either CVal CVal    -> b)
+        -> ((Maybe Int, String) -> (Maybe Int, String) -> b)
+        -> CV                   -> CV                  -> b
+liftCV2 r i f d c s u v m e w x y = case (cvVal x, cvVal y) of
+                                      (CAlgReal   a, CAlgReal   b) -> r a b
+                                      (CInteger   a, CInteger   b) -> i a b
+                                      (CFloat     a, CFloat     b) -> f a b
+                                      (CDouble    a, CDouble    b) -> d a b
+                                      (CChar      a, CChar      b) -> c a b
+                                      (CString    a, CString    b) -> s a b
+                                      (CList      a, CList      b) -> u a b
+                                      (CTuple     a, CTuple     b) -> v a b
+                                      (CMaybe     a, CMaybe     b) -> m a b
+                                      (CEither    a, CEither    b) -> e a b
+                                      (CUserSort  a, CUserSort  b) -> w a b
+                                      _                            -> error $ "SBV.liftCV2: impossible, incompatible args received: " ++ show (x, y)
 
 -- | Map a unary function through a 'CV'.
-mapCV :: (AlgReal -> AlgReal) -> (Integer -> Integer) -> (Float -> Float) -> (Double -> Double) -> (Char -> Char) -> (String -> String) -> ((Maybe Int, String) -> (Maybe Int, String)) -> CV -> CV
+mapCV :: (AlgReal             -> AlgReal)
+      -> (Integer             -> Integer)
+      -> (Float               -> Float)
+      -> (Double              -> Double)
+      -> (Char                -> Char)
+      -> (String              -> String)
+      -> ((Maybe Int, String) -> (Maybe Int, String))
+      -> CV
+      -> CV
 mapCV r i f d c s u x  = normCV $ CV (kindOf x) $ case cvVal x of
                                                     CAlgReal  a -> CAlgReal  (r a)
                                                     CInteger  a -> CInteger  (i a)
@@ -222,10 +329,22 @@
                                                     CString   a -> CString   (s a)
                                                     CUserSort a -> CUserSort (u a)
                                                     CList{}     -> error "Data.SBV.mapCV: Unexpected call through mapCV with lists!"
+                                                    CSet{}      -> error "Data.SBV.mapCV: Unexpected call through mapCV with sets!"
                                                     CTuple{}    -> error "Data.SBV.mapCV: Unexpected call through mapCV with tuples!"
+                                                    CMaybe{}    -> error "Data.SBV.mapCV: Unexpected call through mapCV with maybe!"
+                                                    CEither{}   -> error "Data.SBV.mapCV: Unexpected call through mapCV with either!"
 
 -- | Map a binary function through a 'CV'.
-mapCV2 :: (AlgReal -> AlgReal -> AlgReal) -> (Integer -> Integer -> Integer) -> (Float -> Float -> Float) -> (Double -> Double -> Double) -> (Char -> Char -> Char) -> (String -> String -> String) -> ((Maybe Int, String) -> (Maybe Int, String) -> (Maybe Int, String)) -> CV -> CV -> CV
+mapCV2 :: (AlgReal             -> AlgReal             -> AlgReal)
+       -> (Integer             -> Integer             -> Integer)
+       -> (Float               -> Float               -> Float)
+       -> (Double              -> Double              -> Double)
+       -> (Char                -> Char                -> Char)
+       -> (String              -> String              -> String)
+       -> ((Maybe Int, String) -> (Maybe Int, String) -> (Maybe Int, String))
+       -> CV
+       -> CV
+       -> CV
 mapCV2 r i f d c s u x y = case (cvSameType x y, cvVal x, cvVal y) of
                             (True, CAlgReal  a, CAlgReal  b) -> normCV $ CV (kindOf x) (CAlgReal  (r a b))
                             (True, CInteger  a, CInteger  b) -> normCV $ CV (kindOf x) (CInteger  (i a b))
@@ -235,6 +354,9 @@
                             (True, CString   a, CString   b) -> normCV $ CV (kindOf x) (CString   (s a b))
                             (True, CUserSort a, CUserSort b) -> normCV $ CV (kindOf x) (CUserSort (u a b))
                             (True, CList{},     CList{})     -> error "Data.SBV.mapCV2: Unexpected call through mapCV2 with lists!"
+                            (True, CTuple{},    CTuple{})    -> error "Data.SBV.mapCV2: Unexpected call through mapCV2 with tuples!"
+                            (True, CMaybe{},    CMaybe{})    -> error "Data.SBV.mapCV2: Unexpected call through mapCV2 with maybes!"
+                            (True, CEither{},   CEither{})   -> error "Data.SBV.mapCV2: Unexpected call through mapCV2 with eithers!"
                             _                                -> error $ "SBV.mapCV2: impossible, incompatible args received: " ++ show (x, y)
 
 -- | Show instance for 'CV'.
@@ -249,30 +371,47 @@
 -- | Show a CV, with kind info if bool is True
 showCV :: Bool -> CV -> String
 showCV shk w | isBoolean w = show (cvToBool w) ++ (if shk then " :: Bool" else "")
-showCV shk w               = liftCV show show show show show show snd shL shT w ++ kInfo
-      where kInfo | shk  = " :: " ++ showBaseKind (kindOf w)
+showCV shk w               = liftCV show show show show show show snd shL shS shT shMaybe shEither w ++ kInfo
+      where kw = kindOf w
+
+            kInfo | shk  = " :: " ++ showBaseKind kw
                   | True = ""
 
             shL xs = "[" ++ intercalate "," (map (showCV False . CV ke) xs) ++ "]"
-              where ke = case kindOf w of
+              where ke = case kw of
                            KList k -> k
-                           kw      -> error $ "Data.SBV.showCV: Impossible happened, expected list, got: " ++ show kw
+                           _       -> error $ "Data.SBV.showCV: Impossible happened, expected list, got: " ++ show kw
 
+            -- we represent complements as @U - set@. This might be confusing, but is utterly cute!
+            shS :: RCSet CVal -> String
+            shS eru = case eru of
+                        RegularSet    e              -> sh e
+                        ComplementSet e | Set.null e -> "U"
+                                        | True       -> "U - " ++ sh e
+              where sh xs = "{" ++ intercalate "," (map (showCV False . CV ke) (Set.toList xs)) ++ "}"
+                    ke = case kw of
+                           KSet k -> k
+                           _      -> error $ "Data.SBV.showCV: Impossible happened, expected set, got: " ++ show kw
+
             shT :: [CVal] -> String
             shT xs = "(" ++ intercalate "," xs' ++ ")"
-              where xs' = case kindOf w of
+              where xs' = case kw of
                             KTuple ks | length ks == length xs -> zipWith (\k x -> showCV False (CV k x)) ks xs
-                            kw -> error $ "Data.SBV.showCV: Impossible happened, expected tuple (of length " ++ show (length xs) ++ "), got: " ++ show kw
+                            _   -> error $ "Data.SBV.showCV: Impossible happened, expected tuple (of length " ++ show (length xs) ++ "), got: " ++ show kw
 
--- | A version of show for kinds that says Bool instead of SBool
-showBaseKind :: Kind -> String
-showBaseKind k@KUninterpreted{} = show k   -- Leave user-sorts untouched!
-showBaseKind (KList k)          = "[" ++ showBaseKind k ++ "]"
-showBaseKind (KTuple ks)        = "(" ++ intercalate ", " (map showBaseKind ks) ++ ")"
-showBaseKind k = case show k of
-                   ('S':sk) -> sk
-                   s        -> s
+            shMaybe :: Maybe CVal -> String
+            shMaybe c = case (c, kw) of
+                          (Nothing, KMaybe{}) -> "Nothing"
+                          (Just x,  KMaybe k) -> "Just " ++ showCV False (CV k x)
+                          _                   -> error $ "Data.SBV.showCV: Impossible happened, expected maybe, got: " ++ show kw
 
+            shEither :: Either CVal CVal -> String
+            shEither val
+              | KEither k1 k2 <- kw = case val of
+                                        Left  x -> "Left "  ++ showCV False (CV k1 x)
+                                        Right y -> "Right " ++ showCV False (CV k2 y)
+              | True                = error $ "Data.SBV.showCV: Impossible happened, expected sum, got: " ++ show kw
+
 -- | Create a constant word from an integral.
 mkConstCV :: Integral a => Kind -> a -> CV
 mkConstCV KBool                a = normCV $ CV KBool      (CInteger (toInteger a))
@@ -285,7 +424,10 @@
 mkConstCV KString              a = error $ "Unexpected call to mkConstCV (String) with value: " ++ show (toInteger a)
 mkConstCV (KUninterpreted s _) a = error $ "Unexpected call to mkConstCV with uninterpreted kind: " ++ s ++ " with value: " ++ show (toInteger a)
 mkConstCV k@KList{}            a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
+mkConstCV k@KSet{}             a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
 mkConstCV k@KTuple{}           a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
+mkConstCV k@KMaybe{}           a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
+mkConstCV k@KEither{}          a = error $ "Unexpected call to mkConstCV (" ++ show k ++ ") with value: " ++ show (toInteger a)
 
 -- | Generate a random constant value ('CVal') of the correct kind.
 randomCVal :: Kind -> IO CVal
@@ -304,7 +446,19 @@
     KUninterpreted s _ -> error $ "Unexpected call to randomCVal with uninterpreted kind: " ++ s
     KList ek           -> do l <- randomRIO (0, 100)
                              CList <$> replicateM l (randomCVal ek)
+    KSet  ek           -> do i <- randomIO                           -- regular or complement
+                             l <- randomRIO (0, 100)                 -- some set upto 100 elements
+                             vals <- Set.fromList <$> replicateM l (randomCVal ek)
+                             return $ CSet $ if i then RegularSet vals else ComplementSet vals
     KTuple ks          -> CTuple <$> traverse randomCVal ks
+    KMaybe ke          -> do i <- randomIO
+                             if i
+                                then return $ CMaybe Nothing
+                                else CMaybe . Just <$> randomCVal ke
+    KEither k1 k2      -> do i <- randomIO
+                             if i
+                                then CEither . Left  <$> randomCVal k1
+                                else CEither . Right <$> randomCVal k2
   where
     bounds :: Bool -> Int -> (Integer, Integer)
     bounds False w = (0, 2^w - 1)
@@ -313,3 +467,5 @@
 -- | Generate a random constant value ('CV') of the correct kind.
 randomCV :: Kind -> IO CV
 randomCV k = CV k <$> randomCVal k
+
+{-# ANN module ("HLint: ignore Redundant if" :: String) #-}
diff --git a/Data/SBV/Core/Data.hs b/Data/SBV/Core/Data.hs
--- a/Data/SBV/Core/Data.hs
+++ b/Data/SBV/Core/Data.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.Data
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -23,17 +23,18 @@
 {-# LANGUAGE TypeApplications      #-}
 {-# LANGUAGE TypeFamilies          #-}
 {-# LANGUAGE TypeOperators         #-}
-{-# LANGUAGE TypeSynonymInstances  #-}
 
 module Data.SBV.Core.Data
  ( SBool, SWord8, SWord16, SWord32, SWord64
  , SInt8, SInt16, SInt32, SInt64, SInteger, SReal, SFloat, SDouble, SChar, SString, SList
- , STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
+ , SEither, SMaybe
+ , STuple, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7, STuple8
+ , RCSet(..), SSet
  , nan, infinity, sNaN, sInfinity, RoundingMode(..), SRoundingMode
  , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
  , sRNE, sRNA, sRTP, sRTN, sRTZ
  , SymVal(..)
- , CV(..), CVal(..), AlgReal(..), AlgRealPoly, ExtCV(..), GeneralizedCV(..), isRegularCV, cvSameType, cvToBool
+ , CV(..), CVal(..), AlgReal(..), AlgRealPoly(..), ExtCV(..), GeneralizedCV(..), isRegularCV, cvSameType, cvToBool
  , mkConstCV ,liftCV2, mapCV, mapCV2
  , SV(..), trueSV, falseSV, trueCV, falseCV, normCV
  , SVal(..)
@@ -161,7 +162,21 @@
 -- Note that lists can be nested, i.e., we do allow lists of lists of ... items.
 type SList a = SBV [a]
 
--- | Symbolic 2-tuple.
+-- | Symbolic 'Either'
+type SEither a b = SBV (Either a b)
+
+-- | Symbolic 'Maybe'
+type SMaybe a = SBV (Maybe a)
+
+-- | Symbolic 'Data.Set'. Note that we use 'RCSet', which supports
+-- both regular sets and complements, i.e., those obtained from the
+-- universal set (of the right type) by removing elements.
+type SSet a = SBV (RCSet a)
+
+-- | Symbolic 2-tuple. NB. 'STuple' and 'STuple2' are equivalent.
+type STuple a b = SBV (a, b)
+
+-- | Symbolic 2-tuple. NB. 'STuple' and 'STuple2' are equivalent.
 type STuple2 a b = SBV (a, b)
 
 -- | Symbolic 3-tuple.
@@ -252,6 +267,9 @@
 infixr 1 .=>
 (.=>) :: SBool -> SBool -> SBool
 x .=> y = sNot x .|| y
+-- NB. Do *not* try to optimize @x .=> x = True@ here! If constants go through, it'll get simplified.
+-- The case "x .=> x" can hit is extremely rare, and the getAllSatResult function relies on this
+-- trick to generate constraints in the unlucky case of ui-function models.
 
 -- | Symbolic boolean equivalence
 infixr 1 .<=>
@@ -364,10 +382,10 @@
 -- two instances of this class. Note that we use this mechanism
 -- internally and do not export it from SBV.
 class SolverContext m where
-   -- | Add a constraint, any satisfying instance must satisfy this condition
-   constrain       :: SBool -> m ()
-   -- | Add a soft constraint. The solver will try to satisfy this condition if possible, but won't if it cannot
-   softConstrain   :: SBool -> m ()
+   -- | Add a constraint, any satisfying instance must satisfy this condition.
+   constrain :: SBool -> m ()
+   -- | Add a soft constraint. The solver will try to satisfy this condition if possible, but won't if it cannot.
+   softConstrain :: SBool -> m ()
    -- | Add a named constraint. The name is used in unsat-core extraction.
    namedConstraint :: String -> SBool -> m ()
    -- | Add a constraint, with arbitrary attributes. Used in interpolant generation.
@@ -384,7 +402,11 @@
    -- is in milliseconds. Also see the function 'Data.SBV.Control.timeOut' for finer level
    -- control of time-outs, directly from SBV.
    setTimeOut :: Integer -> m ()
+   -- | Get the state associated with this context
+   contextState :: m State
 
+   {-# MINIMAL constrain, softConstrain, namedConstraint, constrainWithAttribute, setOption, contextState #-}
+
    -- time-out, logic, and info are  simply options in our implementation, so default implementation suffices
    setTimeOut t = setOption $ OptionKeyword ":timeout" [show t]
    setLogic     = setOption . SetLogic
@@ -431,7 +453,7 @@
 -- * Symbolic Values
 -------------------------------------------------------------------------------
 -- | A 'SymVal' is a potential symbolic value that can be created instances of to be fed to a symbolic program.
-class (HasKind a, Ord a, Typeable a) => SymVal a where
+class (HasKind a, Typeable a) => SymVal a where
   -- | Generalization of 'Data.SBV.mkSymVal'
   mkSymVal :: MonadSymbolic m => Maybe Quantifier -> Maybe String -> m (SBV a)
   -- | Turn a literal constant to symbolic
diff --git a/Data/SBV/Core/Floating.hs b/Data/SBV/Core/Floating.hs
--- a/Data/SBV/Core/Floating.hs
+++ b/Data/SBV/Core/Floating.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.Floating
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,14 +9,20 @@
 -- Implementation of floating-point operations mapping to SMT-Lib2 floats
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE Rank2Types          #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE DefaultSignatures    #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE Rank2Types           #-}
+{-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeApplications     #-}
+{-# LANGUAGE TypeFamilies         #-}
 
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
 module Data.SBV.Core.Floating (
-         IEEEFloating(..), IEEEFloatConvertable(..)
+         IEEEFloating(..), IEEEFloatConvertible(..)
        , sFloatAsSWord32, sDoubleAsSWord64, sWord32AsSFloat, sWord64AsSDouble
        , blastSFloat, blastSDouble
+       , sFloatAsComparableSWord32, sDoubleAsComparableSWord64
        ) where
 
 import qualified Data.Numbers.CrackNum as CN (wordToFloat, wordToDouble, floatToWord, doubleToWord)
@@ -26,11 +32,22 @@
 
 import Data.Proxy
 
+import Data.SBV.Core.AlgReals (isExactRational)
+
 import Data.SBV.Core.Data
 import Data.SBV.Core.Model
-import Data.SBV.Core.AlgReals (isExactRational)
+import Data.SBV.Core.Symbolic (addSValOptGoal)
+
 import Data.SBV.Utils.Numeric
 
+-- For doctest use only
+--
+-- $setup
+-- >>> :set -XTypeApplications
+-- >>> :set -XRankNTypes
+-- >>> :set -XScopedTypeVariables
+-- >>> import Data.SBV.Provers.Prover (prove)
+
 -- | A class of floating-point (IEEE754) operations, some of
 -- which behave differently based on rounding modes. Note that unless
 -- the rounding mode is concretely RoundNearestTiesToEven, we will
@@ -141,109 +158,196 @@
 -- | SDouble instance
 instance IEEEFloating Double
 
--- | Capture convertability from/to FloatingPoint representations
--- NB. 'fromSFloat' and 'fromSDouble' are underspecified when given
--- when given a @NaN@, @+oo@, or @-oo@ value that cannot be represented
--- in the target domain. For these inputs, we define the result to be +0, arbitrarily.
-class IEEEFloatConvertable a where
-  fromSFloat  :: SRoundingMode -> SFloat  -> SBV a
-  toSFloat    :: SRoundingMode -> SBV a   -> SFloat
-  fromSDouble :: SRoundingMode -> SDouble -> SBV a
-  toSDouble   :: SRoundingMode -> SBV a   -> SDouble
-
--- | A generic converter that will work for most of our instances. (But not all!)
-genericFPConverter :: forall a r. (SymVal a, HasKind r, SymVal r, Num r) => Maybe (a -> Bool) -> Maybe (SBV a -> SBool) -> (a -> r) -> SRoundingMode -> SBV a -> SBV r
-genericFPConverter mbConcreteOK mbSymbolicOK converter rm f
-  | Just w <- unliteral f, Just RoundNearestTiesToEven <- unliteral rm, check w
-  = literal $ converter w
-  | Just symCheck <- mbSymbolicOK
-  = ite (symCheck f) result (literal 0)
-  | True
-  = result
-  where result  = SBV (SVal kTo (Right (cache y)))
-        check w = maybe True ($ w) mbConcreteOK
-        kFrom   = kindOf f
-        kTo     = kindOf (Proxy @r)
-        y st    = do msv <- sbvToSV st rm
-                     xsv <- sbvToSV st f
-                     newExpr st kTo (SBVApp (IEEEFP (FP_Cast kFrom kTo msv)) [xsv])
+-- | Capture convertability from/to FloatingPoint representations.
+--
+-- Conversions to float: 'toSFloat' and 'toSDouble' simply return the
+-- nearest representable float from the given type based on the rounding
+-- mode provided.
+--
+-- Conversions from float: 'fromSFloat' and 'fromSDouble' functions do
+-- the reverse conversion. However some care is needed when given values
+-- that are not representable in the integral target domain. For instance,
+-- converting an 'SFloat' to an 'SInt8' is problematic. The rules are as follows:
+--
+-- If the input value is a finite point and when rounded in the given rounding mode to an
+-- integral value lies within the target bounds, then that result is returned.
+-- (This is the regular interpretation of rounding in IEEE754.)
+--
+-- Otherwise (i.e., if the integral value in the float or double domain) doesn't
+-- fit into the target type, then the result is unspecified. Note that if the input
+-- is @+oo@, @-oo@, or @NaN@, then the result is unspecified.
+--
+-- Due to the unspecified nature of conversions, SBV will never constant fold
+-- conversions from floats to integral values. That is, you will always get a
+-- symbolic value as output. (Conversions from floats to other floats will be
+-- constant folded. Conversions from integral values to floats will also be
+-- constant folded.)
+--
+-- Note that unspecified really means unspecified: In particular, SBV makes
+-- no guarantees about matching the behavior between what you might get in
+-- Haskell, via SMT-Lib, or the C-translation. If the input value is out-of-bounds
+-- as defined above, or is @NaN@ or @oo@ or @-oo@, then all bets are off. In particular
+-- C and SMTLib are decidedly undefine this case, though that doesn't mean they do the
+-- same thing! Same goes for Haskell, which seems to convert via Int64, but we do
+-- not model that behavior in SBV as it doesn't seem to be intentional nor well documented.
+--
+-- You can check for @NaN@, @oo@ and @-oo@, using the predicates 'fpIsNaN', 'fpIsInfinite',
+-- and 'fpIsPositive', 'fpIsNegative' predicates, respectively; and do the proper conversion
+-- based on your needs. (0 is a good choice, as are min/max bounds of the target type.)
+--
+-- Currently, SBV provides no predicates to check if a value would lie within range for a
+-- particular conversion task, as this depends on the rounding mode and the types involved
+-- and can be rather tricky to determine. (See <http://github.com/LeventErkok/sbv/issues/456>
+-- for a discussion of the issues involved.) In a future release, we hope to be able to
+-- provide underflow and overflow predicates for these conversions as well.
+class SymVal a => IEEEFloatConvertible a where
+  -- | Convert from an IEEE74 single precision float.
+  fromSFloat :: SRoundingMode -> SFloat -> SBV a
+  fromSFloat = genericFromFloat
 
--- | Check that a given float is a point
-ptCheck :: IEEEFloating a => Maybe (SBV a -> SBool)
-ptCheck = Just fpIsPoint
+  -- | Convert to an IEEE-754 Single-precision float.
+  --
+  -- >>> :{
+  -- roundTrip :: forall a. (Eq a, IEEEFloatConvertible a) => SRoundingMode -> SBV a -> SBool
+  -- roundTrip m x = fromSFloat m (toSFloat m x) .== x
+  -- :}
+  --
+  -- >>> prove $ roundTrip @Int8
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Word8
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Int16
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Word16
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Int32
+  -- Falsifiable. Counter-example:
+  --   s0 = RoundNearestTiesToEven :: RoundingMode
+  --   s1 =            -2130176960 :: Int32
+  --
+  -- Note how we get a failure on `Int32`. The counter-example value is not representable exactly as a single precision float:
+  --
+  -- >>> toRational (-2130176960 :: Float)
+  -- (-2130177024) % 1
+  --
+  -- Note how the numerator is different, it is off by 64. This is hardly surprising, since floats become sparser as
+  -- the magnitude increases to be able to cover all the integer values representable.
+  toSFloat :: SRoundingMode -> SBV a -> SFloat
 
-instance IEEEFloatConvertable Int8 where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+  -- default definition if we have an integral like
+  default toSFloat :: Integral a => SRoundingMode -> SBV a -> SFloat
+  toSFloat = genericToFloat (Just . fromRational . fromIntegral)
 
-instance IEEEFloatConvertable Int16 where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+  -- | Convert from an IEEE74 double precision float.
+  fromSDouble :: SRoundingMode -> SDouble -> SBV a
+  fromSDouble = genericFromFloat
 
-instance IEEEFloatConvertable Int32 where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+  -- | Convert to an IEEE-754 Double-precision float.
+  --
+  -- >>> :{
+  -- roundTrip :: forall a. (Eq a, IEEEFloatConvertible a) => SRoundingMode -> SBV a -> SBool
+  -- roundTrip m x = fromSDouble m (toSDouble m x) .== x
+  -- :}
+  --
+  -- >>> prove $ roundTrip @Int8
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Word8
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Int16
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Word16
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Int32
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Word32
+  -- Q.E.D.
+  -- >>> prove $ roundTrip @Int64
+  -- Falsifiable. Counter-example:
+  --   s0 = RoundNearestTiesToEven :: RoundingMode
+  --   s1 =    4611686018427387902 :: Int64
+  --
+  -- Just like in the `SFloat` case, once we reach 64-bits, we no longer can exactly represent the
+  -- integer value for all possible values:
+  --
+  -- >>> toRational (4611686018427387902 ::Double)
+  -- 4611686018427387904 % 1
+  --
+  -- In this case the numerator is off by 2!
+  toSDouble :: SRoundingMode -> SBV a -> SDouble
 
-instance IEEEFloatConvertable Int64 where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+  -- default definition if we have an integral like
+  default toSDouble :: Integral a => SRoundingMode -> SBV a -> SDouble
+  toSDouble = genericToFloat (Just . fromRational . fromIntegral)
 
-instance IEEEFloatConvertable Word8 where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+-- | A generic from-float converter. Note that this function does no constant folding since
+-- it's behavior is undefined when the input float is out-of-bounds or not a point.
+genericFromFloat :: forall a r. (IEEEFloating a, IEEEFloatConvertible r)
+                 => SRoundingMode            -- Rounding mode
+                 -> SBV a                    -- Input float/double
+                 -> SBV r
+genericFromFloat rm f = SBV (SVal kTo (Right (cache r)))
+  where kFrom = kindOf f
+        kTo   = kindOf (Proxy @r)
+        r st  = do msv <- sbvToSV st rm
+                   xsv <- sbvToSV st f
+                   newExpr st kTo (SBVApp (IEEEFP (FP_Cast kFrom kTo msv)) [xsv])
 
-instance IEEEFloatConvertable Word16 where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+-- | A generic to-float converter, which will constant-fold as necessary, but only in the sRNE mode.
+genericToFloat :: forall a r. (IEEEFloatConvertible a, IEEEFloating r)
+               => (a -> Maybe r)     -- How to convert concretely, if possible
+               -> SRoundingMode      -- Rounding mode
+               -> SBV a              -- Input convertible
+               -> SBV r
+genericToFloat converter rm i
+  | Just w <- unliteral i, Just RoundNearestTiesToEven <- unliteral rm, Just result <- converter w
+  = literal result
+  | True
+  = SBV (SVal kTo (Right (cache r)))
+  where kFrom = kindOf i
+        kTo   = kindOf (Proxy @r)
+        r st  = do msv <- sbvToSV st rm
+                   xsv <- sbvToSV st i
+                   newExpr st kTo (SBVApp (IEEEFP (FP_Cast kFrom kTo msv)) [xsv])
 
-instance IEEEFloatConvertable Word32 where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+instance IEEEFloatConvertible Int8
+instance IEEEFloatConvertible Int16
+instance IEEEFloatConvertible Int32
+instance IEEEFloatConvertible Int64
+instance IEEEFloatConvertible Word8
+instance IEEEFloatConvertible Word16
+instance IEEEFloatConvertible Word32
+instance IEEEFloatConvertible Word64
+instance IEEEFloatConvertible Integer
 
-instance IEEEFloatConvertable Word64 where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+-- For float and double, skip the conversion if the same and do the constant folding, unlike all others.
+instance IEEEFloatConvertible Float where
+  toSFloat  _ f = f
+  toSDouble     = genericToFloat (Just . fp2fp)
 
-instance IEEEFloatConvertable Float where
-  fromSFloat _ f = f
-  toSFloat   _ f = f
-  fromSDouble    = genericFPConverter Nothing Nothing fp2fp
-  toSDouble      = genericFPConverter Nothing Nothing fp2fp
+  fromSFloat  _  f = f
+  fromSDouble rm f
+    | Just RoundNearestTiesToEven <- unliteral rm
+    , Just fv                     <- unliteral f
+    = literal (fp2fp fv)
+    | True
+    = genericFromFloat rm f
 
-instance IEEEFloatConvertable Double where
-  fromSFloat      = genericFPConverter Nothing Nothing fp2fp
-  toSFloat        = genericFPConverter Nothing Nothing fp2fp
-  fromSDouble _ d = d
-  toSDouble   _ d = d
+instance IEEEFloatConvertible Double where
+  toSFloat      = genericToFloat (Just . fp2fp)
+  toSDouble _ d = d
 
-instance IEEEFloatConvertable Integer where
-  fromSFloat  = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Float -> Integer))
-  toSFloat    = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
-  fromSDouble = genericFPConverter Nothing ptCheck (fromIntegral . (fpRound0 :: Double -> Integer))
-  toSDouble   = genericFPConverter Nothing Nothing (fromRational . fromIntegral)
+  fromSDouble _  d = d
+  fromSFloat  rm d
+    | Just RoundNearestTiesToEven <- unliteral rm
+    , Just dv                     <- unliteral d
+    = literal (fp2fp dv)
+    | True
+    = genericFromFloat rm d
 
 -- For AlgReal; be careful to only process exact rationals concretely
-instance IEEEFloatConvertable AlgReal where
-  fromSFloat  = genericFPConverter Nothing                ptCheck (fromRational . fpRatio0)
-  toSFloat    = genericFPConverter (Just isExactRational) Nothing (fromRational . toRational)
-  fromSDouble = genericFPConverter Nothing                ptCheck (fromRational . fpRatio0)
-  toSDouble   = genericFPConverter (Just isExactRational) Nothing (fromRational . toRational)
+instance IEEEFloatConvertible AlgReal where
+  toSFloat  = genericToFloat (\r -> if isExactRational r then Just (fromRational (toRational r)) else Nothing)
+  toSDouble = genericToFloat (\r -> if isExactRational r then Just (fromRational (toRational r)) else Nothing)
 
 -- | Concretely evaluate one arg function, if rounding mode is RoundNearestTiesToEven and we have enough concrete data
 concEval1 :: SymVal a => Maybe (a -> a) -> Maybe SRoundingMode -> SBV a -> Maybe (SBV a)
@@ -442,5 +546,49 @@
   | True                     = SBV (SVal KDouble (Right (cache y)))
   where y st = do xsv <- sbvToSV st dVal
                   newExpr st KDouble (SBVApp (IEEEFP (FP_Reinterpret (kindOf dVal) KDouble)) [xsv])
+
+-- | Convert a float to a comparable 'SWord32'. The trick is to ignore the
+-- sign of -0, and if it's a negative value flip all the bits, and otherwise
+-- only flip the sign bit. This is known as the lexicographic ordering on floats
+-- and it works as long as you do not have a @NaN@.
+sFloatAsComparableSWord32 :: SFloat -> SWord32
+sFloatAsComparableSWord32 f = ite (fpIsNegativeZero f) (sFloatAsComparableSWord32 0) (fromBitsBE $ sNot sb : ite sb (map sNot rest) rest)
+  where (sb : rest) = blastBE $ sFloatAsSWord32 f
+
+-- | Convert a double to a comparable 'SWord64'. The trick is to ignore the
+-- sign of -0, and if it's a negative value flip all the bits, and otherwise
+-- only flip the sign bit. This is known as the lexicographic ordering on doubles
+-- and it works as long as you do not have a @NaN@.
+sDoubleAsComparableSWord64 :: SDouble -> SWord64
+sDoubleAsComparableSWord64 d = ite (fpIsNegativeZero d) (sDoubleAsComparableSWord64 0) (fromBitsBE $ sNot sb : ite sb (map sNot rest) rest)
+  where (sb : rest) = blastBE $ sDoubleAsSWord64 d
+
+-- | 'Float' instance for 'Metric' goes through the lexicographic ordering on 'Word32'.
+-- It implicitly makes sure that the value is not @NaN@.
+instance Metric Float where
+
+   type MetricSpace Float = Word32
+   toMetricSpace          = sFloatAsComparableSWord32
+   fromMetricSpace        = sWord32AsSFloat
+
+   msMinimize nm o = do constrain $ sNot $ fpIsNaN o
+                        addSValOptGoal $ unSBV `fmap` Minimize nm (toMetricSpace o)
+
+   msMaximize nm o = do constrain $ sNot $ fpIsNaN o
+                        addSValOptGoal $ unSBV `fmap` Maximize nm (toMetricSpace o)
+
+-- | 'Double' instance for 'Metric' goes through the lexicographic ordering on 'Word64'.
+-- It implicitly makes sure that the value is not @NaN@.
+instance Metric Double where
+
+   type MetricSpace Double = Word64
+   toMetricSpace           = sDoubleAsComparableSWord64
+   fromMetricSpace         = sWord64AsSDouble
+
+   msMinimize nm o = do constrain $ sNot $ fpIsNaN o
+                        addSValOptGoal $ unSBV `fmap` Minimize nm (toMetricSpace o)
+
+   msMaximize nm o = do constrain $ sNot $ fpIsNaN o
+                        addSValOptGoal $ unSBV `fmap` Maximize nm (toMetricSpace o)
 
 {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Data/SBV/Core/Kind.hs b/Data/SBV/Core/Kind.hs
--- a/Data/SBV/Core/Kind.hs
+++ b/Data/SBV/Core/Kind.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.Kind
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,20 +9,21 @@
 -- Internal data-structures for the sbv library
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE DefaultSignatures    #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE LambdaCase           #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeApplications     #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-{-# LANGUAGE ViewPatterns         #-}
+{-# LANGUAGE DefaultSignatures   #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE LambdaCase          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE ViewPatterns        #-}
 
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
-module Data.SBV.Core.Kind (Kind(..), HasKind(..), constructUKind, smtType) where
+module Data.SBV.Core.Kind (Kind(..), HasKind(..), constructUKind, smtType, hasUninterpretedSorts, showBaseKind, needsFlattening) where
 
 import qualified Data.Generics as G (Data(..), DataType, dataTypeName, dataTypeOf, tyconUQname, dataTypeConstrs, constrFields)
 
+import Data.Char (isSpace)
+
 import Data.Int
 import Data.Word
 import Data.SBV.Core.AlgReals
@@ -46,7 +47,10 @@
           | KChar
           | KString
           | KList Kind
+          | KSet  Kind
           | KTuple [Kind]
+          | KMaybe  Kind
+          | KEither Kind Kind
           deriving (Eq, Ord)
 
 -- | The interesting about the show instance is that it can tell apart two kinds nicely; since it conveniently
@@ -64,8 +68,40 @@
   show KString              = "SString"
   show KChar                = "SChar"
   show (KList e)            = "[" ++ show e ++ "]"
+  show (KSet  e)            = "{" ++ show e ++ "}"
   show (KTuple m)           = "(" ++ intercalate ", " (show <$> m) ++ ")"
+  show (KMaybe k)           = "SMaybe "  ++ kindParen (showBaseKind k)
+  show (KEither k1 k2)      = "SEither " ++ kindParen (showBaseKind k1) ++ " " ++ kindParen (showBaseKind k2)
 
+-- | A version of show for kinds that says Bool instead of SBool
+showBaseKind :: Kind -> String
+showBaseKind = sh
+  where sh k@KBool             = noS (show k)
+        sh k@KBounded{}        = noS (show k)
+        sh k@KUnbounded        = noS (show k)
+        sh k@KReal             = noS (show k)
+        sh k@KUninterpreted{}  = show k     -- Leave user-sorts untouched!
+        sh k@KFloat            = noS (show k)
+        sh k@KDouble           = noS (show k)
+        sh k@KChar             = noS (show k)
+        sh k@KString           = noS (show k)
+        sh (KList k)           = "[" ++ sh k ++ "]"
+        sh (KSet k)            = "{" ++ sh k ++ "}"
+        sh (KTuple ks)         = "(" ++ intercalate ", " (map sh ks) ++ ")"
+        sh (KMaybe k)          = "Maybe "  ++ kindParen (sh k)
+        sh (KEither k1 k2)     = "Either " ++ kindParen (sh k1) ++ " " ++ kindParen (sh k2)
+
+        -- Drop the initial S if it's there
+        noS ('S':s) = s
+        noS s       = s
+
+-- | Put parens if necessary. This test is rather crummy, but seems to work ok
+kindParen :: String -> String
+kindParen s@('[':_) = s
+kindParen s@('(':_) = s
+kindParen s | any isSpace s = '(' : s ++ ")"
+            | True          = s
+
 -- | How the type maps to SMT land
 smtType :: Kind -> String
 smtType KBool                = "Bool"
@@ -76,10 +112,13 @@
 smtType KDouble              = "(_ FloatingPoint 11 53)"
 smtType KString              = "String"
 smtType KChar                = "(_ BitVec 8)"
-smtType (KList k)            = "(Seq " ++ smtType k ++ ")"
+smtType (KList k)            = "(Seq "   ++ smtType k ++ ")"
+smtType (KSet  k)            = "(Array " ++ smtType k ++ " Bool)"
 smtType (KUninterpreted s _) = s
 smtType (KTuple [])          = "SBVTuple0"
 smtType (KTuple kinds)       = "(SBVTuple" ++ show (length kinds) ++ " " ++ unwords (smtType <$> kinds) ++ ")"
+smtType (KMaybe k)           = "(SBVMaybe " ++ smtType k ++ ")"
+smtType (KEither k1 k2)      = "(SBVEither "  ++ smtType k1 ++ " " ++ smtType k2 ++ ")"
 
 instance Eq  G.DataType where
    a == b = G.tyconUQname (G.dataTypeName a) == G.tyconUQname (G.dataTypeName b)
@@ -99,7 +138,10 @@
                     KString          -> False
                     KChar            -> False
                     KList{}          -> False
+                    KSet{}           -> False
                     KTuple{}         -> False
+                    KMaybe{}         -> False
+                    KEither{}        -> False
 
 -- | Construct an uninterpreted/enumerated kind from a piece of data; we distinguish simple enumerations as those
 -- are mapped to proper SMT-Lib2 data-types; while others go completely uninterpreted
@@ -141,12 +183,15 @@
   isReal          :: a -> Bool
   isFloat         :: a -> Bool
   isDouble        :: a -> Bool
-  isInteger       :: a -> Bool
+  isUnbounded     :: a -> Bool
   isUninterpreted :: a -> Bool
   isChar          :: a -> Bool
   isString        :: a -> Bool
   isList          :: a -> Bool
+  isSet           :: a -> Bool
   isTuple         :: a -> Bool
+  isMaybe         :: a -> Bool
+  isEither        :: a -> Bool
   showType        :: a -> String
   -- defaults
   hasSign x = kindHasSign (kindOf x)
@@ -162,7 +207,10 @@
                   KString            -> error "SBV.HasKind.intSizeOf((S)Double)"
                   KChar              -> error "SBV.HasKind.intSizeOf((S)Char)"
                   KList ek           -> error $ "SBV.HasKind.intSizeOf((S)List)" ++ show ek
+                  KSet  ek           -> error $ "SBV.HasKind.intSizeOf((S)Set)"  ++ show ek
                   KTuple tys         -> error $ "SBV.HasKind.intSizeOf((S)Tuple)" ++ show tys
+                  KMaybe k           -> error $ "SBV.HasKind.intSizeOf((S)Maybe)" ++ show k
+                  KEither k1 k2      -> error $ "SBV.HasKind.intSizeOf((S)Either)" ++ show (k1, k2)
 
   isBoolean       (kindOf -> KBool{})          = True
   isBoolean       _                            = False
@@ -179,8 +227,8 @@
   isDouble        (kindOf -> KDouble{})        = True
   isDouble        _                            = False
 
-  isInteger       (kindOf -> KUnbounded{})     = True
-  isInteger       _                            = False
+  isUnbounded     (kindOf -> KUnbounded{})     = True
+  isUnbounded     _                            = False
 
   isUninterpreted (kindOf -> KUninterpreted{}) = True
   isUninterpreted _                            = False
@@ -194,9 +242,18 @@
   isList          (kindOf -> KList{})          = True
   isList          _                            = False
 
+  isSet           (kindOf -> KSet{})           = True
+  isSet           _                            = False
+
   isTuple         (kindOf -> KTuple{})         = True
   isTuple         _                            = False
 
+  isMaybe         (kindOf -> KMaybe{})         = True
+  isMaybe         _                            = False
+
+  isEither        (kindOf -> KEither{})        = True
+  isEither        _                            = False
+
   showType = show . kindOf
 
   -- default signature for uninterpreted/enumerated kinds
@@ -223,6 +280,24 @@
 instance HasKind Double  where kindOf _ = KDouble
 instance HasKind Char    where kindOf _ = KChar
 
+-- | Do we have a completely uninterpreted sort lying around anywhere?
+hasUninterpretedSorts :: Kind -> Bool
+hasUninterpretedSorts KBool                        = False
+hasUninterpretedSorts KBounded{}                   = False
+hasUninterpretedSorts KUnbounded                   = False
+hasUninterpretedSorts KReal                        = False
+hasUninterpretedSorts (KUninterpreted _ (Right _)) = False  -- These are the enumerated sorts, and they are perfectly fine
+hasUninterpretedSorts (KUninterpreted _ (Left  _)) = True   -- These are the completely uninterpreted sorts, which we are looking for here
+hasUninterpretedSorts KFloat                       = False
+hasUninterpretedSorts KDouble                      = False
+hasUninterpretedSorts KChar                        = False
+hasUninterpretedSorts KString                      = False
+hasUninterpretedSorts (KList k)                    = hasUninterpretedSorts k
+hasUninterpretedSorts (KSet k)                     = hasUninterpretedSorts k
+hasUninterpretedSorts (KTuple ks)                  = any hasUninterpretedSorts ks
+hasUninterpretedSorts (KMaybe k)                   = hasUninterpretedSorts k
+hasUninterpretedSorts (KEither k1 k2)              = any hasUninterpretedSorts [k1, k2]
+
 instance (Typeable a, HasKind a) => HasKind [a] where
    kindOf x | isKString @[a] x = KString
             | True             = KList (kindOf (Proxy @a))
@@ -253,3 +328,28 @@
 
 instance (HasKind a, HasKind b, HasKind c, HasKind d, HasKind e, HasKind f, HasKind g, HasKind h) => HasKind (a, b, c, d, e, f, g, h) where
   kindOf _ = KTuple [kindOf (Proxy @a), kindOf (Proxy @b), kindOf (Proxy @c), kindOf (Proxy @d), kindOf (Proxy @e), kindOf (Proxy @f), kindOf (Proxy @g), kindOf (Proxy @h)]
+
+instance (HasKind a, HasKind b) => HasKind (Either a b) where
+  kindOf _ = KEither (kindOf (Proxy @a)) (kindOf (Proxy @b))
+
+instance HasKind a => HasKind (Maybe a) where
+  kindOf _ = KMaybe (kindOf (Proxy @a))
+
+-- | Should we ask the solver to flatten the output? This comes in handy so output is parseable
+-- Essentially, we're being conservative here and simply requesting flattening anything that has
+-- some structure to it.
+needsFlattening :: Kind -> Bool
+needsFlattening KBool            = False
+needsFlattening KBounded{}       = False
+needsFlattening KUnbounded       = False
+needsFlattening KReal            = False
+needsFlattening KUninterpreted{} = False
+needsFlattening KFloat           = False
+needsFlattening KDouble          = False
+needsFlattening KChar            = False
+needsFlattening KString          = False
+needsFlattening KList{}          = True
+needsFlattening KSet{}           = True
+needsFlattening KTuple{}         = True
+needsFlattening KMaybe{}         = True
+needsFlattening KEither{}        = True
diff --git a/Data/SBV/Core/Model.hs b/Data/SBV/Core/Model.hs
--- a/Data/SBV/Core/Model.hs
+++ b/Data/SBV/Core/Model.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.Model
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,26 +9,30 @@
 -- Instance declarations for our symbolic world
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE BangPatterns          #-}
-{-# LANGUAGE DefaultSignatures     #-}
-{-# LANGUAGE FlexibleContexts      #-}
-{-# LANGUAGE FlexibleInstances     #-}
-{-# LANGUAGE Rank2Types            #-}
-{-# LANGUAGE ScopedTypeVariables   #-}
-{-# LANGUAGE TypeApplications      #-}
-{-# LANGUAGE TypeOperators         #-}
-{-# LANGUAGE TypeSynonymInstances  #-}
+{-# LANGUAGE BangPatterns        #-}
+{-# LANGUAGE DefaultSignatures   #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE TypeFamilies        #-}
+{-# LANGUAGE TypeOperators       #-}
 
-{-# OPTIONS_GHC -fno-warn-orphans  #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Data.SBV.Core.Model (
-    Mergeable(..), Equality(..), EqSymbolic(..), OrdSymbolic(..), SDivisible(..), Uninterpreted(..), Metric(..), assertWithPenalty, SIntegral, SFiniteBits(..)
-  , ite, iteLazy, sFromIntegral, sShiftLeft, sShiftRight, sRotateLeft, sRotateRight, sSignedShiftArithRight, (.^)
+    Mergeable(..), Equality(..), EqSymbolic(..), OrdSymbolic(..), SDivisible(..), Uninterpreted(..), Metric(..), minimize, maximize, assertWithPenalty, SIntegral, SFiniteBits(..)
+  , ite, iteLazy, sFromIntegral, sShiftLeft, sShiftRight, sRotateLeft, sBarrelRotateLeft, sRotateRight, sBarrelRotateRight, sSignedShiftArithRight, (.^)
   , oneIf, genVar, genVar_, forall, forall_, exists, exists_
   , pbAtMost, pbAtLeast, pbExactly, pbLe, pbGe, pbEq, pbMutexed, pbStronglyMutexed
-  , sBool, sBools, sWord8, sWord8s, sWord16, sWord16s, sWord32
-  , sWord32s, sWord64, sWord64s, sInt8, sInt8s, sInt16, sInt16s, sInt32, sInt32s, sInt64
-  , sInt64s, sInteger, sIntegers, sReal, sReals, sFloat, sFloats, sDouble, sDoubles, sChar, sChars, sString, sStrings, sList, sLists, sTuple, sTuples
+  , sBool, sBool_, sBools, sWord8, sWord8_, sWord8s, sWord16, sWord16_, sWord16s, sWord32, sWord32_, sWord32s
+  , sWord64, sWord64_, sWord64s, sInt8, sInt8_, sInt8s, sInt16, sInt16_, sInt16s, sInt32, sInt32_, sInt32s, sInt64, sInt64_
+  , sInt64s, sInteger, sInteger_, sIntegers, sReal, sReal_, sReals, sFloat, sFloat_, sFloats, sDouble, sDouble_, sDoubles
+  , sChar, sChar_, sChars, sString, sString_, sStrings, sList, sList_, sLists
+  , sTuple, sTuple_, sTuples
+  , sEither, sEither_, sEithers, sMaybe, sMaybe_, sMaybes
+  , sSet, sSet_, sSets
   , solve
   , slet
   , sRealToSInteger, label, observe, observeIf
@@ -57,6 +61,8 @@
 import Data.String (IsString(..))
 import Data.Word   (Word8, Word16, Word32, Word64)
 
+import qualified Data.Set as Set
+
 import Data.Proxy
 import Data.Dynamic (fromDynamic, toDyn)
 
@@ -65,6 +71,8 @@
 import qualified Test.QuickCheck         as QC (quickCheckResult, counterexample)
 import qualified Test.QuickCheck.Monadic as QC (monadicIO, run, assert, pre, monitor)
 
+import qualified Data.Foldable as F (toList)
+
 import Data.SBV.Core.AlgReals
 import Data.SBV.Core.Data
 import Data.SBV.Core.Symbolic
@@ -232,6 +240,47 @@
          lcs = length cs
 fromCVTup i inp = error $ "SymVal.fromCVTup: Impossible happened. Non-tuple received: " ++ show (i, inp)
 
+instance (SymVal a, SymVal b) => SymVal (Either a b) where
+  mkSymVal = genMkSymVar (kindOf (Proxy @(Either a b)))
+
+  literal s
+    | Left  a <- s = mk $ Left  (toCV a)
+    | Right b <- s = mk $ Right (toCV b)
+    where k  = kindOf (Proxy @(Either a b))
+
+          mk = SBV . SVal k . Left . CV k . CEither
+
+  fromCV (CV (KEither k1 _ ) (CEither (Left c)))  = Left  $ fromCV $ CV k1 c
+  fromCV (CV (KEither _  k2) (CEither (Right c))) = Right $ fromCV $ CV k2 c
+  fromCV bad                                   = error $ "SymVal.fromCV (Either): Malformed either received: " ++ show bad
+
+instance SymVal a => SymVal (Maybe a) where
+  mkSymVal = genMkSymVar (kindOf (Proxy @(Maybe a)))
+
+  literal s
+    | Nothing <- s = mk Nothing
+    | Just  a <- s = mk $ Just (toCV a)
+    where k = kindOf (Proxy @(Maybe a))
+
+          mk = SBV . SVal k . Left . CV k . CMaybe
+
+  fromCV (CV (KMaybe _) (CMaybe Nothing))  = Nothing
+  fromCV (CV (KMaybe k) (CMaybe (Just x))) = Just $ fromCV $ CV k x
+  fromCV bad                               = error $ "SymVal.fromCV (Maybe): Malformed sum received: " ++ show bad
+
+instance (Ord a, SymVal a) => SymVal (RCSet a) where
+  mkSymVal = genMkSymVar (kindOf (Proxy @(RCSet a)))
+
+  literal eur = SBV $ SVal k $ Left $ CV k $ CSet $ dir $ Set.map toCV s
+    where (dir, s) = case eur of
+                      RegularSet x    -> (RegularSet,    x)
+                      ComplementSet x -> (ComplementSet, x)
+          k        = kindOf (Proxy @(RCSet a))
+
+  fromCV (CV (KSet a) (CSet (RegularSet    s))) = RegularSet    $ Set.map (fromCV . CV a) s
+  fromCV (CV (KSet a) (CSet (ComplementSet s))) = ComplementSet $ Set.map (fromCV . CV a) s
+  fromCV bad                                    = error $ "SymVal.fromCV (Set): Malformed set received: " ++ show bad
+
 -- | SymVal for 0-tuple (i.e., unit)
 instance SymVal () where
   mkSymVal   = genMkSymVar (KTuple [])
@@ -295,10 +344,15 @@
 -- necessary, as they are mere aliases for 'symbolic' and 'symbolics', but
 -- they nonetheless make programming easier.
 ------------------------------------------------------------------------------------
+
 -- | Generalization of 'Data.SBV.sBool'
 sBool :: MonadSymbolic m => String -> m SBool
 sBool = symbolic
 
+-- | Generalization of 'Data.SBV.sBool_'
+sBool_ :: MonadSymbolic m => m SBool
+sBool_ = free_
+
 -- | Generalization of 'Data.SBV.sBools'
 sBools :: MonadSymbolic m => [String] -> m [SBool]
 sBools = symbolics
@@ -307,6 +361,10 @@
 sWord8 :: MonadSymbolic m => String -> m SWord8
 sWord8 = symbolic
 
+-- | Generalization of 'Data.SBV.sWord8_'
+sWord8_ :: MonadSymbolic m => m SWord8
+sWord8_ = free_
+
 -- | Generalization of 'Data.SBV.sWord8s'
 sWord8s :: MonadSymbolic m => [String] -> m [SWord8]
 sWord8s = symbolics
@@ -315,6 +373,10 @@
 sWord16 :: MonadSymbolic m => String -> m SWord16
 sWord16 = symbolic
 
+-- | Generalization of 'Data.SBV.sWord16_'
+sWord16_ :: MonadSymbolic m => m SWord16
+sWord16_ = free_
+
 -- | Generalization of 'Data.SBV.sWord16s'
 sWord16s :: MonadSymbolic m => [String] -> m [SWord16]
 sWord16s = symbolics
@@ -323,6 +385,10 @@
 sWord32 :: MonadSymbolic m => String -> m SWord32
 sWord32 = symbolic
 
+-- | Generalization of 'Data.SBV.sWord32_'
+sWord32_ :: MonadSymbolic m => m SWord32
+sWord32_ = free_
+
 -- | Generalization of 'Data.SBV.sWord32s'
 sWord32s :: MonadSymbolic m => [String] -> m [SWord32]
 sWord32s = symbolics
@@ -331,6 +397,10 @@
 sWord64 :: MonadSymbolic m => String -> m SWord64
 sWord64 = symbolic
 
+-- | Generalization of 'Data.SBV.sWord64_'
+sWord64_ :: MonadSymbolic m => m SWord64
+sWord64_ = free_
+
 -- | Generalization of 'Data.SBV.sWord64s'
 sWord64s :: MonadSymbolic m => [String] -> m [SWord64]
 sWord64s = symbolics
@@ -339,6 +409,10 @@
 sInt8 :: MonadSymbolic m => String -> m SInt8
 sInt8 = symbolic
 
+-- | Generalization of 'Data.SBV.sInt8_'
+sInt8_ :: MonadSymbolic m => m SInt8
+sInt8_ = free_
+
 -- | Generalization of 'Data.SBV.sInt8s'
 sInt8s :: MonadSymbolic m => [String] -> m [SInt8]
 sInt8s = symbolics
@@ -347,6 +421,10 @@
 sInt16 :: MonadSymbolic m => String -> m SInt16
 sInt16 = symbolic
 
+-- | Generalization of 'Data.SBV.sInt16_'
+sInt16_ :: MonadSymbolic m => m SInt16
+sInt16_ = free_
+
 -- | Generalization of 'Data.SBV.sInt16s'
 sInt16s :: MonadSymbolic m => [String] -> m [SInt16]
 sInt16s = symbolics
@@ -355,6 +433,10 @@
 sInt32 :: MonadSymbolic m => String -> m SInt32
 sInt32 = symbolic
 
+-- | Generalization of 'Data.SBV.sInt32_'
+sInt32_ :: MonadSymbolic m => m SInt32
+sInt32_ = free_
+
 -- | Generalization of 'Data.SBV.sInt32s'
 sInt32s :: MonadSymbolic m => [String] -> m [SInt32]
 sInt32s = symbolics
@@ -363,6 +445,10 @@
 sInt64 :: MonadSymbolic m => String -> m SInt64
 sInt64 = symbolic
 
+-- | Generalization of 'Data.SBV.sInt64_'
+sInt64_ :: MonadSymbolic m => m SInt64
+sInt64_ = free_
+
 -- | Generalization of 'Data.SBV.sInt64s'
 sInt64s :: MonadSymbolic m => [String] -> m [SInt64]
 sInt64s = symbolics
@@ -371,6 +457,10 @@
 sInteger:: MonadSymbolic m => String -> m SInteger
 sInteger = symbolic
 
+-- | Generalization of 'Data.SBV.sInteger_'
+sInteger_:: MonadSymbolic m => m SInteger
+sInteger_ = free_
+
 -- | Generalization of 'Data.SBV.sIntegers'
 sIntegers :: MonadSymbolic m => [String] -> m [SInteger]
 sIntegers = symbolics
@@ -379,6 +469,10 @@
 sReal:: MonadSymbolic m => String -> m SReal
 sReal = symbolic
 
+-- | Generalization of 'Data.SBV.sReal_'
+sReal_:: MonadSymbolic m => m SReal
+sReal_ = free_
+
 -- | Generalization of 'Data.SBV.sReals'
 sReals :: MonadSymbolic m => [String] -> m [SReal]
 sReals = symbolics
@@ -387,6 +481,10 @@
 sFloat :: MonadSymbolic m => String -> m SFloat
 sFloat = symbolic
 
+-- | Generalization of 'Data.SBV.sFloat_'
+sFloat_ :: MonadSymbolic m => m SFloat
+sFloat_ = free_
+
 -- | Generalization of 'Data.SBV.sFloats'
 sFloats :: MonadSymbolic m => [String] -> m [SFloat]
 sFloats = symbolics
@@ -395,6 +493,10 @@
 sDouble :: MonadSymbolic m => String -> m SDouble
 sDouble = symbolic
 
+-- | Generalization of 'Data.SBV.sDouble_'
+sDouble_ :: MonadSymbolic m => m SDouble
+sDouble_ = free_
+
 -- | Generalization of 'Data.SBV.sDoubles'
 sDoubles :: MonadSymbolic m => [String] -> m [SDouble]
 sDoubles = symbolics
@@ -403,14 +505,22 @@
 sChar :: MonadSymbolic m => String -> m SChar
 sChar = symbolic
 
--- | Generalization of 'Data.SBV.sString'
-sString :: MonadSymbolic m => String -> m SString
-sString = symbolic
+-- | Generalization of 'Data.SBV.sChar_'
+sChar_ :: MonadSymbolic m => m SChar
+sChar_ = free_
 
 -- | Generalization of 'Data.SBV.sChars'
 sChars :: MonadSymbolic m => [String] -> m [SChar]
 sChars = symbolics
 
+-- | Generalization of 'Data.SBV.sString'
+sString :: MonadSymbolic m => String -> m SString
+sString = symbolic
+
+-- | Generalization of 'Data.SBV.sString_'
+sString_ :: MonadSymbolic m => m SString
+sString_ = free_
+
 -- | Generalization of 'Data.SBV.sStrings'
 sStrings :: MonadSymbolic m => [String] -> m [SString]
 sStrings = symbolics
@@ -419,6 +529,10 @@
 sList :: (SymVal a, MonadSymbolic m) => String -> m (SList a)
 sList = symbolic
 
+-- | Generalization of 'Data.SBV.sList_'
+sList_ :: (SymVal a, MonadSymbolic m) => m (SList a)
+sList_ = free_
+
 -- | Generalization of 'Data.SBV.sLists'
 sLists :: (SymVal a, MonadSymbolic m) => [String] -> m [SList a]
 sLists = symbolics
@@ -427,10 +541,50 @@
 sTuple :: (SymVal tup, MonadSymbolic m) => String -> m (SBV tup)
 sTuple = symbolic
 
+-- | Generalization of 'Data.SBV.sTuple_'
+sTuple_ :: (SymVal tup, MonadSymbolic m) => m (SBV tup)
+sTuple_ = free_
+
 -- | Generalization of 'Data.SBV.sTuples'
 sTuples :: (SymVal tup, MonadSymbolic m) => [String] -> m [SBV tup]
 sTuples = symbolics
 
+-- | Generalization of 'Data.SBV.sEither'
+sEither :: (SymVal a, SymVal b, MonadSymbolic m) => String -> m (SEither a b)
+sEither = symbolic
+
+-- | Generalization of 'Data.SBV.sEither_'
+sEither_ :: (SymVal a, SymVal b, MonadSymbolic m) => m (SEither a b)
+sEither_ = free_
+
+-- | Generalization of 'Data.SBV.sEithers'
+sEithers :: (SymVal a, SymVal b, MonadSymbolic m) => [String] -> m [SEither a b]
+sEithers = symbolics
+
+-- | Generalization of 'Data.SBV.sMaybe'
+sMaybe :: (SymVal a, MonadSymbolic m) => String -> m (SMaybe a)
+sMaybe = symbolic
+
+-- | Generalization of 'Data.SBV.sMaybe_'
+sMaybe_ :: (SymVal a, MonadSymbolic m) => m (SMaybe a)
+sMaybe_ = free_
+
+-- | Generalization of 'Data.SBV.sMaybes'
+sMaybes :: (SymVal a, MonadSymbolic m) => [String] -> m [SMaybe a]
+sMaybes = symbolics
+
+-- | Generalization of 'Data.SBV.sSet'
+sSet :: (Ord a, SymVal a, MonadSymbolic m) => String -> m (SSet a)
+sSet = symbolic
+
+-- | Generalization of 'Data.SBV.sMaybe_'
+sSet_ :: (Ord a, SymVal a, MonadSymbolic m) => m (SSet a)
+sSet_ = free_
+
+-- | Generalization of 'Data.SBV.sMaybes'
+sSets :: (Ord a, SymVal a, MonadSymbolic m) => [String] -> m [SSet a]
+sSets = symbolics
+
 -- | Generalization of 'Data.SBV.solve'
 solve :: MonadSymbolic m => [SBool] -> m SBool
 solve = return . sAnd
@@ -485,12 +639,24 @@
 
 -- | Symbolic Equality. Note that we can't use Haskell's 'Eq' class since Haskell insists on returning Bool
 -- Comparing symbolic values will necessarily return a symbolic value.
-infix 4 .==, ./=
+infix 4 .==, ./=, .===, ./==
 class EqSymbolic a where
   -- | Symbolic equality.
   (.==) :: a -> a -> SBool
   -- | Symbolic inequality.
   (./=) :: a -> a -> SBool
+  -- | Strong equality. On floats ('SFloat'/'SDouble'), strong equality is object equality; that
+  -- is @NaN == NaN@ holds, but @+0 == -0@ doesn't. On other types, (.===) is simply (.==).
+  -- Note that (.==) is the /right/ notion of equality for floats per IEEE754 specs, since by
+  -- definition @+0 == -0@ and @NaN@ equals no other value including itself. But occasionally
+  -- we want to be stronger and state @NaN@ equals @NaN@ and @+0@ and @-0@ are different from
+  -- each other. In a context where your type is concrete, simply use `Data.SBV.fpIsEqualObject`. But in
+  -- a polymorphic context, use the strong equality instead.
+  --
+  -- NB. If you do not care about or work with floats, simply use (.==) and (./=).
+  (.===) :: a -> a -> SBool
+  -- | Negation of strong equality. Equaivalent to negation of (.===) on all types.
+  (./==) :: a -> a -> SBool
 
   -- | Returns (symbolic) 'sTrue' if all the elements of the given list are different.
   distinct :: [a] -> SBool
@@ -502,7 +668,9 @@
   sElem    :: a -> [a] -> SBool
   {-# MINIMAL (.==) #-}
 
-  x ./= y = sNot (x .== y)
+  x ./=  y = sNot (x .==  y)
+  x .=== y = x .== y
+  x ./== y = sNot (x .=== y)
 
   allEqual []     = sTrue
   allEqual (x:xs) = sAll (x .==) xs
@@ -559,10 +727,15 @@
 for natural reasons..
 -}
 
+-- It is tempting to put in an @Eq a@ superclass here. But doing so
+-- is complicated, as it requires all underlying types to have equality,
+-- which is at best shaky for algebraic reals and sets. So, leave it out.
 instance EqSymbolic (SBV a) where
   SBV x .== SBV y = SBV (svEqual x y)
   SBV x ./= SBV y = SBV (svNotEqual x y)
 
+  SBV x .=== SBV y = SBV (svStrongEqual x y)
+
   -- Custom version of distinct that generates better code for base types
   distinct []                                             = sTrue
   distinct [_]                                            = sTrue
@@ -595,7 +768,7 @@
           isBool (SBV (SVal KBool _)) = True
           isBool _                    = False
 
-instance SymVal a => OrdSymbolic (SBV a) where
+instance (Ord a, SymVal a) => OrdSymbolic (SBV a) where
   SBV x .<  SBV y = SBV (svLessThan x y)
   SBV x .<= SBV y = SBV (svLessEq x y)
   SBV x .>  SBV y = SBV (svGreaterThan x y)
@@ -712,7 +885,7 @@
 -- | Finite bit-length symbolic values. Essentially the same as 'SIntegral', but further leaves out 'Integer'. Loosely
 -- based on Haskell's @FiniteBits@ class, but with more methods defined and structured differently to fit into the
 -- symbolic world view. Minimal complete definition: 'sFiniteBitSize'.
-class (SymVal a, Num a, Bits a) => SFiniteBits a where
+class (Ord a, SymVal a, Num a, Bits a) => SFiniteBits a where
     -- | Bit size.
     sFiniteBitSize      :: SBV a -> Int
     -- | Least significant bit of a word, always stored at index 0.
@@ -833,7 +1006,7 @@
 instance SFiniteBits Int64  where sFiniteBitSize _ = 64
 
 -- | Returns 1 if the boolean is 'sTrue', otherwise 0.
-oneIf :: (Num a, SymVal a) => SBool -> SBV a
+oneIf :: (Ord a, Num a, SymVal a) => SBool -> SBV a
 oneIf t = ite t 1 0
 
 -- | Lift a pseudo-boolean op, performing checks
@@ -982,7 +1155,7 @@
                           blasted
                           (iterate (\x -> x*x) b)
 
-instance (SymVal a, Fractional a) => Fractional (SBV a) where
+instance (Ord a, SymVal a, Fractional a) => Fractional (SBV a) where
   fromRational  = literal . fromRational
   SBV x / sy@(SBV y) | div0 = ite (sy .== 0) 0 res
                      | True = res
@@ -999,13 +1172,16 @@
                       k@KString          -> error $ "Unexpected Fractional case for: " ++ show k
                       k@KChar            -> error $ "Unexpected Fractional case for: " ++ show k
                       k@KList{}          -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KSet{}           -> error $ "Unexpected Fractional case for: " ++ show k
                       k@KUninterpreted{} -> error $ "Unexpected Fractional case for: " ++ show k
                       k@KTuple{}         -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KMaybe{}         -> error $ "Unexpected Fractional case for: " ++ show k
+                      k@KEither{}        -> error $ "Unexpected Fractional case for: " ++ show k
 
 -- | Define Floating instance on SBV's; only for base types that are already floating; i.e., SFloat and SDouble
 -- Note that most of the fields are "undefined" for symbolic values, we add methods as they are supported by SMTLib.
 -- Currently, the only symbolicly available function in this class is sqrt.
-instance (SymVal a, Fractional a, Floating a) => Floating (SBV a) where
+instance (Ord a, SymVal a, Fractional a, Floating a) => Floating (SBV a) where
     pi      = literal pi
     exp     = lift1FNS "exp"     exp
     log     = lift1FNS "log"     log
@@ -1054,7 +1230,7 @@
 -- -1 has all bits set to True for both signed and unsigned values
 -- | Using 'popCount' or 'testBit' on non-concrete values will result in an
 -- error. Use 'sPopCount' or 'sTestBit' instead.
-instance (Num a, Bits a, SymVal a) => Bits (SBV a) where
+instance (Ord a, Num a, Bits a, SymVal a) => Bits (SBV a) where
   SBV x .&. SBV y    = SBV (svAnd x y)
   SBV x .|. SBV y    = SBV (svOr x y)
   SBV x `xor` SBV y  = SBV (svXOr x y)
@@ -1138,15 +1314,35 @@
 -- | Generalization of 'rotateL', when the shift-amount is symbolic. Since Haskell's
 -- 'rotateL' only takes an 'Int' as the shift amount, it cannot be used when we have
 -- a symbolic amount to shift with. The first argument should be a bounded quantity.
-sRotateLeft :: (SIntegral a, SIntegral b, SDivisible (SBV b)) => SBV a -> SBV b -> SBV a
+sRotateLeft :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
 sRotateLeft = liftViaSVal svRotateLeft
 
+-- | An implementation of rotate-left, using a barrel shifter like design. Only works when both
+-- arguments are finite bitvectors, and furthermore when the second argument is unsigned.
+-- The first condition is enforced by the type, but the second is dynamically checked.
+-- We provide this implementation as an alternative to `sRotateLeft` since SMTLib logic
+-- does not support variable argument rotates (as opposed to shifts), and thus this
+-- implementation can produce better code for verification compared to `sRotateLeft`.
+--
+-- >>> prove $ \x y -> (x `sBarrelRotateLeft`  y) `sBarrelRotateRight` (y :: SWord32) .== (x :: SWord64)
+-- Q.E.D.
+sBarrelRotateLeft :: (SFiniteBits a, SFiniteBits b) => SBV a -> SBV b -> SBV a
+sBarrelRotateLeft = liftViaSVal svBarrelRotateLeft
+
 -- | Generalization of 'rotateR', when the shift-amount is symbolic. Since Haskell's
 -- 'rotateR' only takes an 'Int' as the shift amount, it cannot be used when we have
 -- a symbolic amount to shift with. The first argument should be a bounded quantity.
-sRotateRight :: (SIntegral a, SIntegral b, SDivisible (SBV b)) => SBV a -> SBV b -> SBV a
+sRotateRight :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
 sRotateRight = liftViaSVal svRotateRight
 
+-- | An implementation of rotate-right, using a barrel shifter like design. See comments
+-- for `sBarrelRotateLeft` for details.
+--
+-- >>> prove $ \x y -> (x `sBarrelRotateRight` y) `sBarrelRotateLeft`  (y :: SWord32) .== (x :: SWord64)
+-- Q.E.D.
+sBarrelRotateRight :: (SFiniteBits a, SFiniteBits b) => SBV a -> SBV b -> SBV a
+sBarrelRotateRight = liftViaSVal svBarrelRotateRight
+
 -- Enum instance. These instances are suitable for use with concrete values,
 -- and will be less useful for symbolic values around. Note that `fromEnum` requires
 -- a concrete argument for obvious reasons. Other variants (succ, pred, [x..]) etc are similarly
@@ -1328,7 +1524,7 @@
 
 -- | Lift 'quotRem' to symbolic words. Division by 0 is defined s.t. @x/0 = 0@; which
 -- holds even when @x@ is @0@ itself.
-liftQRem :: SymVal a => SBV a -> SBV a -> (SBV a, SBV a)
+liftQRem :: (Eq a, SymVal a) => SBV a -> SBV a -> (SBV a, SBV a)
 liftQRem x y
   | isConcreteZero x
   = (x, x)
@@ -1352,7 +1548,7 @@
 -- | Lift 'divMod' to symbolic words. Division by 0 is defined s.t. @x/0 = 0@; which
 -- holds even when @x@ is @0@ itself. Essentially, this is conversion from quotRem
 -- (truncate to 0) to divMod (truncate towards negative infinity)
-liftDMod :: (SymVal a, Num a, SDivisible (SBV a)) => SBV a -> SBV a -> (SBV a, SBV a)
+liftDMod :: (Ord a, SymVal a, Num a, SDivisible (SBV a)) => SBV a -> SBV a -> (SBV a, SBV a)
 liftDMod x y
   | isConcreteZero x
   = (x, x)
@@ -1418,7 +1614,7 @@
    -- | Total indexing operation. @select xs default index@ is intuitively
    -- the same as @xs !! index@, except it evaluates to @default@ if @index@
    -- underflows/overflows.
-   select :: (SymVal b, Num b) => [a] -> a -> SBV b -> a
+   select :: (Ord b, SymVal b, Num b) => [a] -> a -> SBV b -> a
    -- NB. Earlier implementation of select used the binary-search trick
    -- on the index to chop down the search space. While that is a good trick
    -- in general, it doesn't work for SBV since we do not have any notion of
@@ -1463,7 +1659,7 @@
    | Just mustHold <- unliteral cond
    = if mustHold
      then x
-     else error $ show $ SafeResult ((locInfo . getCallStack) `fmap` cs, msg, Satisfiable defaultSMTCfg (SMTModel [] []))
+     else error $ show $ SafeResult ((locInfo . getCallStack) `fmap` cs, msg, Satisfiable defaultSMTCfg (SMTModel [] Nothing [] []))
    | True
    = SBV $ SVal k $ Right $ cache r
   where k     = kindOf x
@@ -1523,6 +1719,17 @@
    symbolicMerge _ _ _ _ = ()
    select _ _ _ = ()
 
+-- | Construct a useful error message if we hit an unmergeable case.
+cannotMerge :: String -> String -> String -> a
+cannotMerge typ why hint = error $ unlines [ ""
+                                           , "*** Data.SBV.Mergeable: Cannot merge instances of " ++ typ ++ "."
+                                           , "*** While trying to do a symbolic if-then-else with incompatible branch results."
+                                           , "***"
+                                           , "*** " ++ why
+                                           , "*** "
+                                           , "*** Hint: " ++ hint
+                                           ]
+
 -- Mergeable instances for List/Maybe/Either/Array are useful, but can
 -- throw exceptions if there is no structural matching of the results
 -- It's a question whether we should really keep them..
@@ -1531,7 +1738,9 @@
 instance Mergeable a => Mergeable [a] where
   symbolicMerge f t xs ys
     | lxs == lys = zipWith (symbolicMerge f t) xs ys
-    | True       = error $ "SBV.Mergeable.List: No least-upper-bound for lists of differing size " ++ show (lxs, lys)
+    | True       = cannotMerge "lists"
+                               ("Branches produce different sizes: " ++ show lxs ++ " vs " ++ show lys ++ ". Must have the same length.")
+                               "Use the 'SList' type (and Data.SBV.List routines) to model fully symbolic lists."
     where (lxs, lys) = (length xs, length ys)
 
 -- ZipList
@@ -1543,7 +1752,9 @@
 instance Mergeable a => Mergeable (Maybe a) where
   symbolicMerge _ _ Nothing  Nothing  = Nothing
   symbolicMerge f t (Just a) (Just b) = Just $ symbolicMerge f t a b
-  symbolicMerge _ _ a b = error $ "SBV.Mergeable.Maybe: No least-upper-bound for " ++ show (k a, k b)
+  symbolicMerge _ _ a b = cannotMerge "'Maybe' values"
+                                      ("Branches produce different constructors: " ++ show (k a, k b))
+                                      "Instead of an option type, try using a valid bit to indicate when a result is valid."
       where k Nothing = "Nothing"
             k _       = "Just"
 
@@ -1551,7 +1762,9 @@
 instance (Mergeable a, Mergeable b) => Mergeable (Either a b) where
   symbolicMerge f t (Left a)  (Left b)  = Left  $ symbolicMerge f t a b
   symbolicMerge f t (Right a) (Right b) = Right $ symbolicMerge f t a b
-  symbolicMerge _ _ a b = error $ "SBV.Mergeable.Either: No least-upper-bound for " ++ show (k a, k b)
+  symbolicMerge _ _ a b = cannotMerge "'Either' values"
+                                      ("Branches produce different constructors: " ++ show (k a, k b))
+                                      "Consider using a product type by a tag instead."
      where k (Left _)  = "Left"
            k (Right _) = "Right"
 
@@ -1559,7 +1772,9 @@
 instance (Ix a, Mergeable b) => Mergeable (Array a b) where
   symbolicMerge f t a b
     | ba == bb = listArray ba (zipWith (symbolicMerge f t) (elems a) (elems b))
-    | True     = error $ "SBV.Mergeable.Array: No least-upper-bound for rangeSizes" ++ show (k ba, k bb)
+    | True     = cannotMerge "'Array' values"
+                             ("Branches produce different ranges: " ++ show (k ba, k bb))
+                             "Consider using SBV's native arrays 'SArray' and 'SFunArray' instead."
     where [ba, bb] = map bounds [a, b]
           k = rangeSize
 
@@ -1575,44 +1790,99 @@
 
 -- 2-Tuple
 instance (Mergeable a, Mergeable b) => Mergeable (a, b) where
-  symbolicMerge f t (i0, i1) (j0, j1) = (i i0 j0, i i1 j1)
-    where i a b = symbolicMerge f t a b
-  select xs (err1, err2) ind = (select as err1 ind, select bs err2 ind)
+  symbolicMerge f t (i0, i1) (j0, j1) = ( symbolicMerge f t i0 j0
+                                        , symbolicMerge f t i1 j1
+                                        )
+
+  select xs (err1, err2) ind = ( select as err1 ind
+                               , select bs err2 ind
+                               )
     where (as, bs) = unzip xs
 
 -- 3-Tuple
 instance (Mergeable a, Mergeable b, Mergeable c) => Mergeable (a, b, c) where
-  symbolicMerge f t (i0, i1, i2) (j0, j1, j2) = (i i0 j0, i i1 j1, i i2 j2)
-    where i a b = symbolicMerge f t a b
-  select xs (err1, err2, err3) ind = (select as err1 ind, select bs err2 ind, select cs err3 ind)
+  symbolicMerge f t (i0, i1, i2) (j0, j1, j2) = ( symbolicMerge f t i0 j0
+                                                , symbolicMerge f t i1 j1
+                                                , symbolicMerge f t i2 j2
+                                                )
+
+  select xs (err1, err2, err3) ind = ( select as err1 ind
+                                     , select bs err2 ind
+                                     , select cs err3 ind
+                                     )
+
     where (as, bs, cs) = unzip3 xs
 
 -- 4-Tuple
 instance (Mergeable a, Mergeable b, Mergeable c, Mergeable d) => Mergeable (a, b, c, d) where
-  symbolicMerge f t (i0, i1, i2, i3) (j0, j1, j2, j3) = (i i0 j0, i i1 j1, i i2 j2, i i3 j3)
-    where i a b = symbolicMerge f t a b
-  select xs (err1, err2, err3, err4) ind = (select as err1 ind, select bs err2 ind, select cs err3 ind, select ds err4 ind)
+  symbolicMerge f t (i0, i1, i2, i3) (j0, j1, j2, j3) = ( symbolicMerge f t i0 j0
+                                                        , symbolicMerge f t i1 j1
+                                                        , symbolicMerge f t i2 j2
+                                                        , symbolicMerge f t i3 j3
+                                                        )
+
+  select xs (err1, err2, err3, err4) ind = ( select as err1 ind
+                                           , select bs err2 ind
+                                           , select cs err3 ind
+                                           , select ds err4 ind
+                                           )
     where (as, bs, cs, ds) = unzip4 xs
 
 -- 5-Tuple
 instance (Mergeable a, Mergeable b, Mergeable c, Mergeable d, Mergeable e) => Mergeable (a, b, c, d, e) where
-  symbolicMerge f t (i0, i1, i2, i3, i4) (j0, j1, j2, j3, j4) = (i i0 j0, i i1 j1, i i2 j2, i i3 j3, i i4 j4)
-    where i a b = symbolicMerge f t a b
-  select xs (err1, err2, err3, err4, err5) ind = (select as err1 ind, select bs err2 ind, select cs err3 ind, select ds err4 ind, select es err5 ind)
+  symbolicMerge f t (i0, i1, i2, i3, i4) (j0, j1, j2, j3, j4) = ( symbolicMerge f t i0 j0
+                                                                , symbolicMerge f t i1 j1
+                                                                , symbolicMerge f t i2 j2
+                                                                , symbolicMerge f t i3 j3
+                                                                , symbolicMerge f t i4 j4
+                                                                )
+
+  select xs (err1, err2, err3, err4, err5) ind = ( select as err1 ind
+                                                 , select bs err2 ind
+                                                 , select cs err3 ind
+                                                 , select ds err4 ind
+                                                 , select es err5 ind
+                                                 )
     where (as, bs, cs, ds, es) = unzip5 xs
 
 -- 6-Tuple
 instance (Mergeable a, Mergeable b, Mergeable c, Mergeable d, Mergeable e, Mergeable f) => Mergeable (a, b, c, d, e, f) where
-  symbolicMerge f t (i0, i1, i2, i3, i4, i5) (j0, j1, j2, j3, j4, j5) = (i i0 j0, i i1 j1, i i2 j2, i i3 j3, i i4 j4, i i5 j5)
-    where i a b = symbolicMerge f t a b
-  select xs (err1, err2, err3, err4, err5, err6) ind = (select as err1 ind, select bs err2 ind, select cs err3 ind, select ds err4 ind, select es err5 ind, select fs err6 ind)
+  symbolicMerge f t (i0, i1, i2, i3, i4, i5) (j0, j1, j2, j3, j4, j5) = ( symbolicMerge f t i0 j0
+                                                                        , symbolicMerge f t i1 j1
+                                                                        , symbolicMerge f t i2 j2
+                                                                        , symbolicMerge f t i3 j3
+                                                                        , symbolicMerge f t i4 j4
+                                                                        , symbolicMerge f t i5 j5
+                                                                        )
+
+  select xs (err1, err2, err3, err4, err5, err6) ind = ( select as err1 ind
+                                                       , select bs err2 ind
+                                                       , select cs err3 ind
+                                                       , select ds err4 ind
+                                                       , select es err5 ind
+                                                       , select fs err6 ind
+                                                       )
     where (as, bs, cs, ds, es, fs) = unzip6 xs
 
 -- 7-Tuple
 instance (Mergeable a, Mergeable b, Mergeable c, Mergeable d, Mergeable e, Mergeable f, Mergeable g) => Mergeable (a, b, c, d, e, f, g) where
-  symbolicMerge f t (i0, i1, i2, i3, i4, i5, i6) (j0, j1, j2, j3, j4, j5, j6) = (i i0 j0, i i1 j1, i i2 j2, i i3 j3, i i4 j4, i i5 j5, i i6 j6)
-    where i a b = symbolicMerge f t a b
-  select xs (err1, err2, err3, err4, err5, err6, err7) ind = (select as err1 ind, select bs err2 ind, select cs err3 ind, select ds err4 ind, select es err5 ind, select fs err6 ind, select gs err7 ind)
+  symbolicMerge f t (i0, i1, i2, i3, i4, i5, i6) (j0, j1, j2, j3, j4, j5, j6) = ( symbolicMerge f t i0 j0
+                                                                                , symbolicMerge f t i1 j1
+                                                                                , symbolicMerge f t i2 j2
+                                                                                , symbolicMerge f t i3 j3
+                                                                                , symbolicMerge f t i4 j4
+                                                                                , symbolicMerge f t i5 j5
+                                                                                , symbolicMerge f t i6 j6
+                                                                                )
+
+  select xs (err1, err2, err3, err4, err5, err6, err7) ind = ( select as err1 ind
+                                                             , select bs err2 ind
+                                                             , select cs err3 ind
+                                                             , select ds err4 ind
+                                                             , select es err5 ind
+                                                             , select fs err6 ind
+                                                             , select gs err7 ind
+                                                             )
     where (as, bs, cs, ds, es, fs, gs) = unzip7 xs
 
 -- Arbitrary product types, using GHC.Generics
@@ -1919,6 +2189,7 @@
    softConstrain               (SBV c) = imposeConstraint True  []               c
    namedConstraint        nm   (SBV c) = imposeConstraint False [(":named", nm)] c
    constrainWithAttribute atts (SBV c) = imposeConstraint False atts             c
+   contextState                        = symbolicEnv
 
    setOption o = addNewSMTOption  o
 
@@ -1926,33 +2197,89 @@
 assertWithPenalty :: MonadSymbolic m => String -> SBool -> Penalty -> m ()
 assertWithPenalty nm o p = addSValOptGoal $ unSBV `fmap` AssertWithPenalty nm o p
 
--- | Class of metrics we can optimize for. Currently,
+-- | Class of metrics we can optimize for. Currently, booleans,
 -- bounded signed/unsigned bit-vectors, unbounded integers,
--- and algebraic reals can be optimized. (But not, say, SFloat, SDouble, or SBool.)
--- Minimal complete definition: minimize/maximize.
+-- algebraic reals and floats can be optimized. You can add
+-- your instances, but bewared that the 'MetricSpace' should
+-- map your type to something the backend solver understands, which
+-- are limited to unsigned bit-vectors, reals, and unbounded integers
+-- for z3.
 --
 -- A good reference on these features is given in the following paper:
 -- <http://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/nbjorner-scss2014.pdf>.
+--
+-- Minimal completion: None. However, if @MetricSpace@ is not identical to the type, you want
+-- to define 'toMetricSpace' and possbly 'minimize'/'maximize' to add extra constraints as necessary.
 class Metric a where
-  -- | Generalization of 'Data.SBV.minimize'
-  minimize :: MonadSymbolic m => String -> a -> m ()
+  -- | The metric space we optimize the goal over. Usually the same as the type itself, but not always!
+  -- For instance, signed bit-vectors are optimized over their unsigned counterparts, floats are
+  -- optimized over their 'Word32' comparable counterparts, etc.
+  type MetricSpace a :: *
+  type MetricSpace a = a
 
-  -- | Generalization of 'Data.SBV.maximize'
-  maximize :: MonadSymbolic m => String -> a -> m ()
+  -- | Compute the metric value to optimize.
+  toMetricSpace   :: SBV a -> SBV (MetricSpace a)
+  -- | Compute the value itself from the metric corresponding to it.
+  fromMetricSpace :: SBV (MetricSpace a) -> SBV a
 
-  {-# MINIMAL minimize, maximize #-}
+  -- | Minimizing a metric space
+  msMinimize :: (MonadSymbolic m, SolverContext m) => String -> SBV a -> m ()
+  msMinimize nm o = addSValOptGoal $ unSBV `fmap` Minimize nm (toMetricSpace o)
 
-instance Metric SWord8   where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SWord16  where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SWord32  where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SWord64  where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SInt8    where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SInt16   where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SInt32   where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SInt64   where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SInteger where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
-instance Metric SReal    where minimize nm o = addSValOptGoal (unSBV `fmap` Minimize nm o); maximize nm o = addSValOptGoal (unSBV `fmap` Maximize nm o)
+  -- | Maximizing a metric space
+  msMaximize :: (MonadSymbolic m, SolverContext m) => String -> SBV a -> m ()
+  msMaximize nm o = addSValOptGoal $ unSBV `fmap` Maximize nm (toMetricSpace o)
 
+  -- if MetricSpace is the same, we can give a default definition
+  default toMetricSpace :: (a ~ MetricSpace a) => SBV a -> SBV (MetricSpace a)
+  toMetricSpace = id
+
+  default fromMetricSpace :: (a ~ MetricSpace a) => SBV (MetricSpace a) -> SBV a
+  fromMetricSpace = id
+
+-- Booleans assume True is greater than False
+instance Metric Bool where
+  type MetricSpace Bool = Word8
+  toMetricSpace t       = ite t 1 0
+  fromMetricSpace w     = w ./= 0
+
+-- | Generalization of 'Data.SBV.minimize'
+minimize :: (Metric a, MonadSymbolic m, SolverContext m) => String -> SBV a -> m ()
+minimize = msMinimize
+
+-- | Generalization of 'Data.SBV.maximize'
+maximize :: (Metric a, MonadSymbolic m, SolverContext m) => String -> SBV a -> m ()
+maximize = msMaximize
+
+-- Unsigned types, integers, and reals directly optimize
+instance Metric Word8
+instance Metric Word16
+instance Metric Word32
+instance Metric Word64
+instance Metric Integer
+instance Metric AlgReal
+
+-- To optimize signed bounded values, we have to adjust to the range
+instance Metric Int8 where
+  type MetricSpace Int8 = Word8
+  toMetricSpace    x    = sFromIntegral x + 128  -- 2^7
+  fromMetricSpace  x    = sFromIntegral x - 128
+
+instance Metric Int16 where
+  type MetricSpace Int16 = Word16
+  toMetricSpace    x     = sFromIntegral x + 32768  -- 2^15
+  fromMetricSpace  x     = sFromIntegral x - 32768
+
+instance Metric Int32 where
+  type MetricSpace Int32 = Word32
+  toMetricSpace    x     = sFromIntegral x + 2147483648 -- 2^31
+  fromMetricSpace  x     = sFromIntegral x - 2147483648
+
+instance Metric Int64 where
+  type MetricSpace Int64 = Word64
+  toMetricSpace    x     = sFromIntegral x + 9223372036854775808  -- 2^63
+  fromMetricSpace  x     = sFromIntegral x - 9223372036854775808
+
 -- Quickcheck interface on symbolic-booleans..
 instance Testable SBool where
   property (SBV (SVal _ (Left b))) = property (cvToBool b)
@@ -1963,10 +2290,10 @@
                                      QC.pre cond
                                      unless (r || null modelVals) $ QC.monitor (QC.counterexample (complain modelVals))
                                      QC.assert r
-     where test = do (r, Result{resTraces=tvals, resObservables=ovals, resConsts=cs, resConstraints=cstrs, resUIConsts=unints}) <- runSymbolic Concrete prop
+     where test = do (r, Result{resTraces=tvals, resObservables=ovals, resConsts=cs, resConstraints=cstrs, resUIConsts=unints}) <- runSymbolic (Concrete Nothing) prop
 
                      let cval = fromMaybe (error "Cannot quick-check in the presence of uninterpeted constants!") . (`lookup` cs)
-                         cond = and [cvToBool (cval v) | (False, _, v) <- cstrs] -- Only pick-up "hard" constraints, as indicated by False in the fist component
+                         cond = and [cvToBool (cval v) | (False, _, v) <- F.toList cstrs] -- Only pick-up "hard" constraints, as indicated by False in the fist component
 
                          getObservable (nm, f, v) = case v `lookup` cs of
                                                       Just cv -> if f cv then Just (nm, cv) else Nothing
@@ -1978,7 +2305,7 @@
                                Just b  -> return (cond, b, tvals ++ mapMaybe getObservable ovals)
                        us -> noQC us
 
-           complain qcInfo = showModel defaultSMTCfg (SMTModel [] qcInfo)
+           complain qcInfo = showModel defaultSMTCfg (SMTModel [] Nothing qcInfo [])
 
            noQC us         = error $ "Cannot quick-check in the presence of uninterpreted constants: " ++ intercalate ", " us
 
diff --git a/Data/SBV/Core/Operations.hs b/Data/SBV/Core/Operations.hs
--- a/Data/SBV/Core/Operations.hs
+++ b/Data/SBV/Core/Operations.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.Operations
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -21,7 +21,7 @@
   -- ** Basic operations
   , svPlus, svTimes, svMinus, svUNeg, svAbs
   , svDivide, svQuot, svRem, svQuotRem
-  , svEqual, svNotEqual
+  , svEqual, svNotEqual, svStrongEqual, svSetEqual
   , svLessThan, svGreaterThan, svLessEq, svGreaterEq
   , svAnd, svOr, svXOr, svNot
   , svShl, svShr, svRol, svRor
@@ -36,6 +36,7 @@
   , svToWord1, svFromWord1, svTestBit
   , svShiftLeft, svShiftRight
   , svRotateLeft, svRotateRight
+  , svBarrelRotateLeft, svBarrelRotateRight
   , svBlastLE, svBlastBE
   , svAddConstant, svIncrement, svDecrement
   -- ** Basic array operations
@@ -60,6 +61,8 @@
 
 import Data.Ratio
 
+import Data.SBV.Utils.Numeric (fpIsEqualObjectH)
+
 --------------------------------------------------------------------------------
 -- Basic constructors
 
@@ -280,39 +283,88 @@
 
 -- | Equality.
 svEqual :: SVal -> SVal -> SVal
-svEqual = liftSym2B (mkSymOpSC (eqOptBool Equal trueSV) Equal) rationalCheck (==) (==) (==) (==) (==) (==) (==) (==) (==)
+svEqual a b
+  | isSet a && isSet b
+  = svSetEqual a b
+  | True
+  = liftSym2B (mkSymOpSC (eqOptBool Equal trueSV) Equal) rationalCheck (==) (==) (==) (==) (==) (==) (==) (==) (==) (==) (==) a b
 
 -- | Inequality.
 svNotEqual :: SVal -> SVal -> SVal
-svNotEqual = liftSym2B (mkSymOpSC (eqOptBool NotEqual falseSV) NotEqual) rationalCheck (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=)
+svNotEqual a b
+  | isSet a && isSet b
+  = svNot $ svEqual a b
+  | True
+  = liftSym2B (mkSymOpSC (eqOptBool NotEqual falseSV) NotEqual) rationalCheck (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=) (/=) a b
 
+-- | Set equality. Note that we only do constant folding if we get both a regular or both a
+-- complement set. Otherwise we get a symbolic value even if they might be completely concrete.
+svSetEqual :: SVal -> SVal -> SVal
+svSetEqual sa sb
+  | not (isSet sa && isSet sb && kindOf sa == kindOf sb)
+  = error $ "Data.SBV.svSetEqual: Called on ill-typed args: " ++ show (kindOf sa, kindOf sb)
+  | Just (RegularSet a)    <- getSet sa, Just (RegularSet b)    <- getSet sb
+  = svBool (a == b)
+  | Just (ComplementSet a) <- getSet sa, Just (ComplementSet b) <- getSet sb
+  = svBool (a == b)
+  | True
+  = SVal KBool $ Right $ cache r
+  where getSet (SVal _ (Left (CV _ (CSet s)))) = Just s
+        getSet _                               = Nothing
+
+        r st = do sva <- svToSV st sa
+                  svb <- svToSV st sb
+                  newExpr st KBool $ SBVApp (SetOp SetEqual) [sva, svb]
+
+-- | Strong equality. Only matters on floats, where it says @NaN@ equals @NaN@ and @+0@ and @-0@ are different.
+-- Otherwise equivalent to `svEqual`.
+svStrongEqual :: SVal -> SVal -> SVal
+svStrongEqual x y
+  | isFloat x, Just f1 <- getF x, Just f2 <- getF y
+  = svBool $ f1 `fpIsEqualObjectH` f2
+  | isDouble x, Just f1 <- getD x, Just f2 <- getD y
+  = svBool $ f1 `fpIsEqualObjectH` f2
+  | isFloat x || isDouble x
+  = SVal KBool $ Right $ cache r
+  | True
+  = svEqual x y
+  where getF (SVal _ (Left (CV _ (CFloat f)))) = Just f
+        getF _                                 = Nothing
+
+        getD (SVal _ (Left (CV _ (CDouble d)))) = Just d
+        getD _                                  = Nothing
+
+        r st = do sx <- svToSV st x
+                  sy <- svToSV st y
+                  newExpr st KBool (SBVApp (IEEEFP FP_ObjEqual) [sx, sy])
+
 -- | Less than.
 svLessThan :: SVal -> SVal -> SVal
 svLessThan x y
   | isConcreteMax x = svFalse
   | isConcreteMin y = svFalse
-  | True            = liftSym2B (mkSymOpSC (eqOpt falseSV) LessThan) rationalCheck (<) (<) (<) (<) (<) (<) (<) (<) (uiLift "<" (<)) x y
+  | True            = liftSym2B (mkSymOpSC (eqOpt falseSV) LessThan) rationalCheck (<) (<) (<) (<) (<) (<) (<) (<) (<) (<) (uiLift "<" (<)) x y
 
 -- | Greater than.
 svGreaterThan :: SVal -> SVal -> SVal
 svGreaterThan x y
   | isConcreteMin x = svFalse
   | isConcreteMax y = svFalse
-  | True            = liftSym2B (mkSymOpSC (eqOpt falseSV) GreaterThan) rationalCheck (>) (>) (>) (>) (>) (>) (>) (>) (uiLift ">"  (>)) x y
+  | True            = liftSym2B (mkSymOpSC (eqOpt falseSV) GreaterThan) rationalCheck (>) (>) (>) (>) (>) (>) (>) (>) (>) (>) (uiLift ">"  (>)) x y
 
 -- | Less than or equal to.
 svLessEq :: SVal -> SVal -> SVal
 svLessEq x y
   | isConcreteMin x = svTrue
   | isConcreteMax y = svTrue
-  | True            = liftSym2B (mkSymOpSC (eqOpt trueSV) LessEq) rationalCheck (<=) (<=) (<=) (<=) (<=) (<=) (<=) (<=) (uiLift "<=" (<=)) x y
+  | True            = liftSym2B (mkSymOpSC (eqOpt trueSV) LessEq) rationalCheck (<=) (<=) (<=) (<=) (<=) (<=) (<=) (<=) (<=) (<=) (uiLift "<=" (<=)) x y
 
 -- | Greater than or equal to.
 svGreaterEq :: SVal -> SVal -> SVal
 svGreaterEq x y
   | isConcreteMax x = svTrue
   | isConcreteMin y = svTrue
-  | True            = liftSym2B (mkSymOpSC (eqOpt trueSV) GreaterEq) rationalCheck (>=) (>=) (>=) (>=) (>=) (>=) (>=) (>=) (uiLift ">=" (>=)) x y
+  | True            = liftSym2B (mkSymOpSC (eqOpt trueSV) GreaterEq) rationalCheck (>=) (>=) (>=) (>=) (>=) (>=) (>=) (>=) (>=) (>=) (uiLift ">=" (>=)) x y
 
 -- | Bitwise and.
 svAnd :: SVal -> SVal -> SVal
@@ -370,6 +422,9 @@
 
 -- | Shift left by a constant amount. Translates to the "bvshl"
 -- operation in SMT-Lib.
+--
+-- NB. Haskell spec says the behavior is undefined if the shift amount
+-- is negative. We arbitrarily return the value unchanged if this is the case.
 svShl :: SVal -> Int -> SVal
 svShl x i
   | i <= 0
@@ -383,6 +438,9 @@
 -- | Shift right by a constant amount. Translates to either "bvlshr"
 -- (logical shift right) or "bvashr" (arithmetic shift right) in
 -- SMT-Lib, depending on whether @x@ is a signed bitvector.
+--
+-- NB. Haskell spec says the behavior is undefined if the shift amount
+-- is negative. We arbitrarily return the value unchanged if this is the case.
 svShr :: SVal -> Int -> SVal
 svShr x i
   | i <= 0
@@ -397,7 +455,10 @@
         z    = svInteger k 0
         neg1 = svInteger k (-1)
 
--- | Rotate-left, by a constant
+-- | Rotate-left, by a constant.
+--
+-- NB. Haskell spec says the behavior is undefined if the shift amount
+-- is negative. We arbitrarily return the value unchanged if this is the case.
 svRol :: SVal -> Int -> SVal
 svRol x i
   | i <= 0
@@ -409,7 +470,10 @@
                                      (noFloatUnary "rotateL") (noDoubleUnary "rotateL") x
            _ -> svShl x i   -- for unbounded Integers, rotateL is the same as shiftL in Haskell
 
--- | Rotate-right, by a constant
+-- | Rotate-right, by a constant.
+--
+-- NB. Haskell spec says the behavior is undefined if the shift amount
+-- is negative. We arbitrarily return the value unchanged if this is the case.
 svRor :: SVal -> Int -> SVal
 svRor x i
   | i <= 0
@@ -594,11 +658,15 @@
                          -- takes care of that automatically
                          newExpr st kElt (SBVApp (LkUp (idx, kInd, kElt, len) swi swe) [])
 
+-- Change the sign of a bit-vector quantity. Fails if passed a non-bv
 svChangeSign :: Bool -> SVal -> SVal
 svChangeSign s x
+  | not (isBounded x)       = error $ "Data.SBV." ++ nm ++ ": Received non bit-vector kind: " ++ show (kindOf x)
   | Just n <- svAsInteger x = svInteger k n
   | True                    = SVal k (Right (cache y))
   where
+    nm = if s then "svSign" else "svUnsign"
+
     k = KBounded s (intSizeOf x)
     y st = do xsw <- svToSV st x
               newExpr st k (SBVApp (Extract (intSizeOf x - 1) 0) [xsw])
@@ -692,7 +760,7 @@
           | Just xv <- getConst x, Just iv <- getConst i
           = Just $ SVal kx . Left $! normCV $ CV kx (CInteger (xv `opC` shiftAmount iv))
 
-          | isInteger x || isInteger i
+          | isUnbounded x || isUnbounded i
           = bailOut $ "Not yet implemented unbounded/non-constants shifts for " ++ show (kx, ki) ++ ", please file a request!"
 
           | not (isBounded x && isBounded i)
@@ -712,12 +780,12 @@
                 -- like fromIntegral, but more paranoid
                 shiftAmount :: Integer -> Int
                 shiftAmount iv
-                  | iv <= 0                                          = 0
-                  | isInteger i, iv > fromIntegral (maxBound :: Int) = bailOut $ "Unsupported constant unbounded shift with amount: " ++ show iv
-                  | isInteger x                                      = fromIntegral iv
-                  | iv >= fromIntegral ub                            = ub
-                  | not (isBounded x && isBounded i)                 = bailOut $ "Unsupported kinds: " ++ show (kx, ki)
-                  | True                                             = fromIntegral iv
+                  | iv <= 0                                            = 0
+                  | isUnbounded i, iv > fromIntegral (maxBound :: Int) = bailOut $ "Unsupported constant unbounded shift with amount: " ++ show iv
+                  | isUnbounded x                                      = fromIntegral iv
+                  | iv >= fromIntegral ub                              = ub
+                  | not (isBounded x && isBounded i)                   = bailOut $ "Unsupported kinds: " ++ show (kx, ki)
+                  | True                                               = fromIntegral iv
                  where ub = intSizeOf x
 
         -- Overshift is not possible if the bit-size of x won't even fit into the bit-vector size
@@ -778,6 +846,54 @@
           zi = svInteger (kindOf i) 0
           n  = svInteger (kindOf i) (toInteger sx)
 
+-- | A variant of 'svRotateLeft' that uses a barrel-rotate design, which can lead to
+-- better verification code. Only works when both arguments are finite and the second
+-- argument is unsigned.
+svBarrelRotateLeft :: SVal -> SVal -> SVal
+svBarrelRotateLeft x i
+  | not (isBounded x && isBounded i && not (hasSign i))
+  = error $ "Data.SBV.Dynamic.svBarrelRotateLeft: Arguments must be bounded with second argument unsigned. Received: " ++ show (x, i)
+  | Just iv <- svAsInteger i
+  = svRol x $ fromIntegral (iv `rem` fromIntegral (intSizeOf x))
+  | True
+  = barrelRotate svRol x i
+
+-- | A variant of 'svRotateLeft' that uses a barrel-rotate design, which can lead to
+-- better verification code. Only works when both arguments are finite and the second
+-- argument is unsigned.
+svBarrelRotateRight :: SVal -> SVal -> SVal
+svBarrelRotateRight x i
+  | not (isBounded x && isBounded i && not (hasSign i))
+  = error $ "Data.SBV.Dynamic.svBarrelRotateRight: Arguments must be bounded with second argument unsigned. Received: " ++ show (x, i)
+  | Just iv <- svAsInteger i
+  = svRor x $ fromIntegral (iv `rem` fromIntegral (intSizeOf x))
+  | True
+  = barrelRotate svRor x i
+
+-- Barrel rotation, by bit-blasting the argument:
+barrelRotate :: (SVal -> Int -> SVal) -> SVal -> SVal -> SVal
+barrelRotate f a c = loop blasted a
+  where loop :: [(SVal, Integer)] -> SVal -> SVal
+        loop []              acc = acc
+        loop ((b, v) : rest) acc = loop rest (svIte b (f acc (fromInteger v)) acc)
+
+        sa = toInteger $ intSizeOf a
+        n  = svInteger (kindOf c) sa
+
+        -- Reduce by the modulus amount, we need not care about the
+        -- any part larger than the value of the bit-size of the
+        -- argument as it is identity for rotations
+        reducedC = c `svRem` n
+
+        -- blast little-endian, and zip with bit-position
+        blasted = takeWhile significant $ zip (svBlastLE reducedC) [2^i | i <- [(0::Integer)..]]
+
+        -- Any term whose bit-position is larger than our input size
+        -- is insignificant, since the reduction would've put 0's in those
+        -- bits. For instance, if a is 32 bits, and c is 5 bits, then we
+        -- need not look at any position i s.t. 2^i > 32
+        significant (_, pos) = pos < sa
+
 -- | Generalization of 'svRor', where the rotation amount is symbolic.
 -- If the first argument is not bounded, then the this is the same as shift.
 svRotateRight :: SVal -> SVal -> SVal
@@ -1202,13 +1318,32 @@
                   sw2 <- svToSV st b
                   opS st k sw1 sw2
 
-liftSym2 :: (State -> Kind -> SV -> SV -> IO SV) -> (CV -> CV -> Bool) -> (AlgReal -> AlgReal -> AlgReal) -> (Integer -> Integer -> Integer) -> (Float -> Float -> Float) -> (Double -> Double -> Double) -> SVal -> SVal -> SVal
+liftSym2 :: (State -> Kind -> SV -> SV -> IO SV)
+         -> (CV      -> CV      -> Bool)
+         -> (AlgReal -> AlgReal -> AlgReal)
+         -> (Integer -> Integer -> Integer)
+         -> (Float   -> Float   -> Float)
+         -> (Double  -> Double  -> Double)
+         -> SVal     -> SVal    -> SVal
 liftSym2 _   okCV opCR opCI opCF opCD   (SVal k (Left a)) (SVal _ (Left b)) | okCV a b = SVal k . Left  $! mapCV2 opCR opCI opCF opCD noCharLift2 noStringLift2 noUnint2 a b
 liftSym2 opS _    _    _    _    _    a@(SVal k _)        b                            = SVal k $ Right $  liftSV2 opS k a b
 
-liftSym2B :: (State -> Kind -> SV -> SV -> IO SV) -> (CV -> CV -> Bool) -> (AlgReal -> AlgReal -> Bool) -> (Integer -> Integer -> Bool) -> (Float -> Float -> Bool) -> (Double -> Double -> Bool) -> (Char -> Char -> Bool) -> (String -> String -> Bool) -> ([CVal] -> [CVal] -> Bool) -> ([CVal] -> [CVal] -> Bool) -> ((Maybe Int, String) -> (Maybe Int, String) -> Bool) -> SVal -> SVal -> SVal
-liftSym2B _   okCV opCR opCI opCF opCD opCC opCS opCSeq opCTup opUI (SVal _ (Left a)) (SVal _ (Left b)) | okCV a b = svBool (liftCV2 opCR opCI opCF opCD opCC opCS opCSeq opCTup opUI a b)
-liftSym2B opS _    _    _    _    _    _    _    _      _      _    a                 b                            = SVal KBool $ Right $ liftSV2 opS KBool a b
+liftSym2B :: (State -> Kind -> SV -> SV -> IO SV)
+          -> (CV                  -> CV                  -> Bool)
+          -> (AlgReal             -> AlgReal             -> Bool)
+          -> (Integer             -> Integer             -> Bool)
+          -> (Float               -> Float               -> Bool)
+          -> (Double              -> Double              -> Bool)
+          -> (Char                -> Char                -> Bool)
+          -> (String              -> String              -> Bool)
+          -> ([CVal]              -> [CVal]              -> Bool)
+          -> ([CVal]              -> [CVal]              -> Bool)
+          -> (Maybe  CVal         -> Maybe  CVal         -> Bool)
+          -> (Either CVal CVal    -> Either CVal CVal    -> Bool)
+          -> ((Maybe Int, String) -> (Maybe Int, String) -> Bool)
+          -> SVal                 -> SVal                -> SVal
+liftSym2B _   okCV opCR opCI opCF opCD opCC opCS opCSeq opCTup opCMaybe opCEither opUI (SVal _ (Left a)) (SVal _ (Left b)) | okCV a b = svBool (liftCV2 opCR opCI opCF opCD opCC opCS opCSeq opCTup opCMaybe opCEither opUI a b)
+liftSym2B opS _    _    _    _    _    _    _    _      _      _        _         _    a                 b                            = SVal KBool $ Right $ liftSV2 opS KBool a b
 
 -- | Create a symbolic two argument operation; with shortcut optimizations
 mkSymOpSC :: (SV -> SV -> Maybe SV) -> Op -> State -> Kind -> SV -> SV -> IO SV
diff --git a/Data/SBV/Core/Splittable.hs b/Data/SBV/Core/Splittable.hs
--- a/Data/SBV/Core/Splittable.hs
+++ b/Data/SBV/Core/Splittable.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.Splittable
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -11,8 +11,6 @@
 
 {-# LANGUAGE FlexibleInstances      #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE MultiParamTypeClasses  #-}
-{-# LANGUAGE TypeSynonymInstances   #-}
 
 module Data.SBV.Core.Splittable (Splittable(..)) where
 
diff --git a/Data/SBV/Core/Symbolic.hs b/Data/SBV/Core/Symbolic.hs
--- a/Data/SBV/Core/Symbolic.hs
+++ b/Data/SBV/Core/Symbolic.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Core.Symbolic
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -17,14 +17,12 @@
 {-# LANGUAGE FunctionalDependencies     #-}
 {-# LANGUAGE GADTs                      #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE MultiParamTypeClasses      #-}
 {-# LANGUAGE NamedFieldPuns             #-}
 {-# LANGUAGE PatternGuards              #-}
 {-# LANGUAGE Rank2Types                 #-}
 {-# LANGUAGE ScopedTypeVariables        #-}
 {-# LANGUAGE TupleSections              #-}
 {-# LANGUAGE TypeOperators              #-}
-{-# LANGUAGE TypeSynonymInstances       #-}
 {-# LANGUAGE UndecidableInstances       #-} -- for undetermined s in MonadState
 
 {-# OPTIONS_GHC -fno-warn-orphans #-}
@@ -32,7 +30,7 @@
 module Data.SBV.Core.Symbolic
   ( NodeId(..)
   , SV(..), swKind, trueSV, falseSV
-  , Op(..), PBOp(..), OvOp(..), FPOp(..), StrOp(..), SeqOp(..), RegExp(..)
+  , Op(..), PBOp(..), OvOp(..), FPOp(..), StrOp(..), SeqOp(..), SetOp(..), RegExp(..)
   , Quantifier(..), needsExistentials
   , RoundingMode(..)
   , SBVType(..), svUninterpreted, newUninterpreted, addAxiom
@@ -54,14 +52,14 @@
   , SolverCapabilities(..)
   , extractSymbolicSimulationState
   , OptimizeStyle(..), Objective(..), Penalty(..), objectiveName, addSValOptGoal
-  , MonadQuery(..), QueryT(..), Query, Queriable(..), QueryState(..), QueryContext(..)
+  , MonadQuery(..), QueryT(..), Query, Queriable(..), Fresh(..), QueryState(..), QueryContext(..)
   , SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), SMTEngine
   , outputSVal
   ) where
 
 import Control.Arrow               (first, second, (***))
 import Control.DeepSeq             (NFData(..))
-import Control.Monad               (when, unless)
+import Control.Monad               (when)
 import Control.Monad.Except        (MonadError, ExceptT)
 import Control.Monad.Reader        (MonadReader(..), ReaderT, runReaderT,
                                     mapReaderT)
@@ -72,7 +70,7 @@
 import Data.Char                   (isAlpha, isAlphaNum, toLower)
 import Data.IORef                  (IORef, newIORef, readIORef)
 import Data.List                   (intercalate, sortBy)
-import Data.Maybe                  (isJust, fromJust, fromMaybe, listToMaybe)
+import Data.Maybe                  (isJust, fromJust, fromMaybe)
 import Data.String                 (IsString(fromString))
 
 import Data.Time (getCurrentTime, UTCTime)
@@ -174,8 +172,15 @@
         | OverflowOp    OvOp                    -- Overflow-ops, categorized separately
         | StrOp StrOp                           -- String ops, categorized separately
         | SeqOp SeqOp                           -- Sequence ops, categorized separately
+        | SetOp SetOp                           -- Set operations, categorized separately
         | TupleConstructor Int                  -- Construct an n-tuple
         | TupleAccess Int Int                   -- Access element i of an n-tuple; second argument is n
+        | EitherConstructor Kind Kind Bool      -- Construct a sum; False: left, True: right
+        | EitherIs Kind Kind Bool               -- Either branch tester; False: left, True: right
+        | EitherAccess Bool                     -- Either branch access; False: left, True: right
+        | MaybeConstructor Kind Bool            -- Construct a maybe value; False: Nothing, True: Just
+        | MaybeIs Kind Bool                     -- Maybe tester; False: nothing, True: just
+        | MaybeAccess                           -- Maybe branch access; grab the contents of the just
         deriving (Eq, Ord)
 
 -- | Floating point operations
@@ -366,7 +371,7 @@
            | SeqReplace   -- ^ See StrReplace
   deriving (Eq, Ord)
 
--- | Show instance for @SeqOp@. Again, mapping is important.
+-- | Show instance for SeqOp. Again, mapping is important.
 instance Show SeqOp where
   show SeqConcat   = "seq.++"
   show SeqLen      = "seq.len"
@@ -378,6 +383,31 @@
   show SeqSuffixOf = "seq.suffixof"
   show SeqReplace  = "seq.replace"
 
+-- | Set operations.
+data SetOp = SetEqual
+           | SetMember
+           | SetInsert
+           | SetDelete
+           | SetIntersect
+           | SetUnion
+           | SetSubset
+           | SetDifference
+           | SetComplement
+        deriving (Eq, Ord)
+
+-- The show instance for 'SetOp' is merely for debugging, we map them separately so
+-- the mapped strings are less important here.
+instance Show SetOp where
+  show SetEqual      = "=="
+  show SetMember     = "Set.member"
+  show SetInsert     = "Set.insert"
+  show SetDelete     = "Set.delete"
+  show SetIntersect  = "Set.intersect"
+  show SetUnion      = "Set.union"
+  show SetSubset     = "Set.subset"
+  show SetDifference = "Set.difference"
+  show SetComplement = "Set.complement"
+
 -- Show instance for 'Op'. Note that this is largely for debugging purposes, not used
 -- for being read by any tool.
 instance Show Op where
@@ -409,11 +439,25 @@
 
   show (StrOp s)            = show s
   show (SeqOp s)            = show s
+  show (SetOp s)            = show s
 
-  show (TupleConstructor   0) = "SBVTuple0"
+  show (TupleConstructor   0) = "mkSBVTuple0"
   show (TupleConstructor   n) = "mkSBVTuple" ++ show n
   show (TupleAccess      i n) = "proj_" ++ show i ++ "_SBVTuple" ++ show n
 
+  show (EitherConstructor k1 k2  False) = "(_ left_SBVEither "  ++ show (KEither k1 k2) ++ ")"
+  show (EitherConstructor k1 k2  True ) = "(_ right_SBVEither " ++ show (KEither k1 k2) ++ ")"
+  show (EitherIs          k1 k2  False) = "(_ is (left_SBVEither ("  ++ show k1 ++ ") " ++ show (KEither k1 k2) ++ "))"
+  show (EitherIs          k1 k2  True ) = "(_ is (right_SBVEither (" ++ show k2 ++ ") " ++ show (KEither k1 k2) ++ "))"
+  show (EitherAccess             False) = "get_left_SBVEither"
+  show (EitherAccess             True ) = "get_right_SBVEither"
+
+  show (MaybeConstructor k False) = "(_ nothing_SBVMaybe " ++ show (KMaybe k) ++ ")"
+  show (MaybeConstructor k True)  = "(_ just_SBVMaybe "    ++ show (KMaybe k) ++ ")"
+  show (MaybeIs          k False) = "(_ is (nothing_SBVMaybe () "              ++ show (KMaybe k) ++ "))"
+  show (MaybeIs          k True ) = "(_ is (just_SBVMaybe (" ++ show k ++ ") " ++ show (KMaybe k) ++ "))"
+  show MaybeAccess               = "get_just_SBVMaybe"
+
   show op
     | Just s <- op `lookup` syms = s
     | True                       = error "impossible happened; can't find op!"
@@ -431,6 +475,11 @@
 -- arbitrary nestings.
 data Quantifier = ALL | EX deriving Eq
 
+-- | Show instance for 'Quantifier'
+instance Show Quantifier where
+  show ALL = "Forall"
+  show EX  = "Exists"
+
 -- | Are there any existential quantifiers?
 needsExistentials :: [Quantifier] -> Bool
 needsExistentials = (EX `elem`)
@@ -545,12 +594,22 @@
 mapQueryT f = QueryT . f . runQueryT
 {-# INLINE mapQueryT #-}
 
--- | An queriable value.
+-- | Create a fresh variable of some type in the underlying query monad transformer.
+-- For further control on how these variables are projected and embedded, see the
+-- 'Queriable' class.
+class Fresh m a where
+  fresh :: QueryT m a
+
+-- | An queriable value. This is a generalization of the 'Fresh' class, in case one needs
+-- to be more specific about how projections/embeddings are done.
 class Queriable m a b | a -> b where
   -- | ^ Create a new symbolic value of type @a@
-  fresh   :: QueryT m a
+  create  :: QueryT m a
   -- | ^ Extract the current value in a SAT context
-  extract :: a -> QueryT m b
+  project :: a -> QueryT m b
+  -- | ^ Create a literal value. Morally, 'embed' and 'project' are inverses of each other
+  -- via the 'QueryT' monad transformer.
+  embed   :: b -> QueryT m a
 
 -- Have to define this one by hand, because we use ReaderT in the implementation
 instance MonadReader r m => MonadReader r (QueryT m) where
@@ -561,6 +620,9 @@
 -- results from the solver.
 type Query = QueryT IO
 
+instance MonadSymbolic Query where
+   symbolicEnv = queryState
+
 instance NFData OptimizeStyle where
    rnf x = x `seq` ()
 
@@ -585,7 +647,7 @@
                      , resUIConsts    :: [(String, SBVType)]                          -- ^ uninterpreted constants
                      , resAxioms      :: [(String, [String])]                         -- ^ axioms
                      , resAsgns       :: SBVPgm                                       -- ^ assignments
-                     , resConstraints :: [(Bool, [(String, String)], SV)]                   -- ^ additional constraints (boolean)
+                     , resConstraints :: S.Seq (Bool, [(String, String)], SV)         -- ^ additional constraints (boolean)
                      , resAssertions  :: [(String, Maybe CallStack, SV)]              -- ^ assertions
                      , resOutputs     :: [SV]                                         -- ^ outputs
                      }
@@ -618,7 +680,7 @@
                 ++ ["DEFINE"]
                 ++ map (\(s, e) -> "  " ++ shs s ++ " = " ++ show e) (F.toList (pgmAssignments xs))
                 ++ ["CONSTRAINTS"]
-                ++ map (("  " ++) . shCstr) cstrs
+                ++ map (("  " ++) . shCstr) (F.toList cstrs)
                 ++ ["ASSERTIONS"]
                 ++ map (("  "++) . shAssert) asserts
                 ++ ["OUTPUTS"]
@@ -742,20 +804,22 @@
                   IRun   -> True
 
 -- | Different means of running a symbolic piece of code
-data SBVRunMode = SMTMode  IStage Bool SMTConfig -- ^ In regular mode, with a stage. Bool is True if this is SAT.
-                | CodeGen                        -- ^ Code generation mode.
-                | Concrete                       -- ^ Concrete simulation mode.
+data SBVRunMode = SMTMode QueryContext IStage Bool SMTConfig                        -- ^ In regular mode, with a stage. Bool is True if this is SAT.
+                | CodeGen                                                           -- ^ Code generation mode.
+                | Concrete (Maybe (Bool, [((Quantifier, NamedSymVar), Maybe CV)]))  -- ^ Concrete simulation mode, with given environment if any. If Nothing: Random.
 
 -- Show instance for SBVRunMode; debugging purposes only
 instance Show SBVRunMode where
-   show (SMTMode ISetup True  _) = "Satisfiability setup"
-   show (SMTMode ISafe  True  _) = "Safety setup"
-   show (SMTMode IRun   True  _) = "Satisfiability"
-   show (SMTMode ISetup False _) = "Proof setup"
-   show (SMTMode ISafe  False _) = error "ISafe-False is not an expected/supported combination for SBVRunMode!"
-   show (SMTMode IRun   False _) = "Proof"
-   show CodeGen                  = "Code generation"
-   show Concrete                 = "Concrete evaluation"
+   show (SMTMode qc ISetup True  _)  = "Satisfiability setup (" ++ show qc ++ ")"
+   show (SMTMode qc ISafe  True  _)  = "Safety setup (" ++ show qc ++ ")"
+   show (SMTMode qc IRun   True  _)  = "Satisfiability (" ++ show qc ++ ")"
+   show (SMTMode qc ISetup False _)  = "Proof setup (" ++ show qc ++ ")"
+   show (SMTMode qc ISafe  False _)  = error $ "ISafe-False is not an expected/supported combination for SBVRunMode! (" ++ show qc ++ ")"
+   show (SMTMode qc IRun   False _)  = "Proof (" ++ show qc ++ ")"
+   show CodeGen                      = "Code generation"
+   show (Concrete Nothing)           = "Concrete evaluation with random values"
+   show (Concrete (Just (True, _)))  = "Concrete evaluation during model validation for sat"
+   show (Concrete (Just (False, _))) = "Concrete evaluation during model validation for prove"
 
 -- | Is this a CodeGen run? (i.e., generating code)
 isCodeGenMode :: State -> IO Bool
@@ -766,32 +830,35 @@
                                              CodeGen    -> True
 
 -- | The state in query mode, i.e., additional context
-data IncState = IncState { rNewInps   :: IORef [NamedSymVar]   -- always existential!
-                         , rNewKinds  :: IORef KindSet
-                         , rNewConsts :: IORef CnstMap
-                         , rNewArrs   :: IORef ArrayMap
-                         , rNewTbls   :: IORef TableMap
-                         , rNewUIs    :: IORef UIMap
-                         , rNewAsgns  :: IORef SBVPgm
+data IncState = IncState { rNewInps        :: IORef [NamedSymVar]   -- always existential!
+                         , rNewKinds       :: IORef KindSet
+                         , rNewConsts      :: IORef CnstMap
+                         , rNewArrs        :: IORef ArrayMap
+                         , rNewTbls        :: IORef TableMap
+                         , rNewUIs         :: IORef UIMap
+                         , rNewAsgns       :: IORef SBVPgm
+                         , rNewConstraints :: IORef (S.Seq (Bool, [(String, String)], SV))
                          }
 
 -- | Get a new IncState
 newIncState :: IO IncState
 newIncState = do
-        is  <- newIORef []
-        ks  <- newIORef Set.empty
-        nc  <- newIORef Map.empty
-        am  <- newIORef IMap.empty
-        tm  <- newIORef Map.empty
-        ui  <- newIORef Map.empty
-        pgm <- newIORef (SBVPgm S.empty)
-        return IncState { rNewInps   = is
-                        , rNewKinds  = ks
-                        , rNewConsts = nc
-                        , rNewArrs   = am
-                        , rNewTbls   = tm
-                        , rNewUIs    = ui
-                        , rNewAsgns  = pgm
+        is    <- newIORef []
+        ks    <- newIORef Set.empty
+        nc    <- newIORef Map.empty
+        am    <- newIORef IMap.empty
+        tm    <- newIORef Map.empty
+        ui    <- newIORef Map.empty
+        pgm   <- newIORef (SBVPgm S.empty)
+        cstrs <- newIORef S.empty
+        return IncState { rNewInps        = is
+                        , rNewKinds       = ks
+                        , rNewConsts      = nc
+                        , rNewArrs        = am
+                        , rNewTbls        = tm
+                        , rNewUIs         = ui
+                        , rNewAsgns       = pgm
+                        , rNewConstraints = cstrs
                         }
 
 -- | Get a new IncState
@@ -814,7 +881,7 @@
                     , rUsedKinds   :: IORef KindSet
                     , rUsedLbls    :: IORef (Set.Set String)
                     , rinps        :: IORef ([(Quantifier, NamedSymVar)], [NamedSymVar]) -- User defined, and internal existential
-                    , rConstraints :: IORef [(Bool, [(String, String)], SV)]
+                    , rConstraints :: IORef (S.Seq (Bool, [(String, String)], SV))
                     , routs        :: IORef [SV]
                     , rtblMap      :: IORef TableMap
                     , spgm         :: IORef SBVPgm
@@ -877,9 +944,23 @@
 -- | This instance is only defined so that we can define an instance for
 -- 'Data.Bits.Bits'. '==' and '/=' simply throw an error.
 instance Eq SVal where
-  a == b = error $ "Comparing symbolic bit-vectors; Use (.==) instead. Received: " ++ show (a, b)
-  a /= b = error $ "Comparing symbolic bit-vectors; Use (./=) instead. Received: " ++ show (a, b)
+  a == b = noEquals "==" ".==" (show a, show b)
+  a /= b = noEquals "/=" "./=" (show a, show b)
 
+-- Bail out nicely.
+noEquals :: String -> String -> (String, String) -> a
+noEquals o n (l, r) = error $ unlines [ ""
+                                      , "*** Data.SBV: Comparing symbolic values using Haskell's Eq class!"
+                                      , "***"
+                                      , "*** Received:    " ++ l ++ "  " ++ o ++ " " ++ r
+                                      , "*** Instead use: " ++ l ++ " "  ++ n ++ " " ++ r
+                                      , "***"
+                                      , "*** The Eq instance for symbolic values are necessiated only because"
+                                      , "*** of the Bits class requirement. You must use symbolic equality"
+                                      , "*** operators instead. (And complain to Haskell folks that they"
+                                      , "*** remove the 'Eq' superclass from 'Bits'!.)"
+                                      ]
+
 -- | Things we do not support in interactive mode, at least for now!
 noInteractive :: [String] -> a
 noInteractive ss = error $ unlines $  ""
@@ -896,8 +977,8 @@
         R.modifyIORef' (field st) update
         rm <- readIORef runMode
         case rm of
-          SMTMode IRun _ _ -> interactiveUpdate
-          _                -> return ()
+          SMTMode _ IRun _ _ -> interactiveUpdate
+          _                  -> return ()
 
 -- | Modify the incremental state
 modifyIncState  :: State -> (IncState -> IORef a) -> (a -> a) -> IO ()
@@ -970,14 +1051,20 @@
 internalVariable st k = do (sv, nm) <- newSV st k
                            rm <- readIORef (runMode st)
                            let q = case rm of
-                                     SMTMode    _ True  _ -> EX
-                                     SMTMode    _ False _ -> ALL
+                                     SMTMode  _ _ True  _ -> EX
+                                     SMTMode  _ _ False _ -> ALL
                                      CodeGen              -> ALL
                                      Concrete{}           -> ALL
-                           modifyState st rinps (first ((:) (q, (sv, "__internal_sbv_" ++ nm))))
-                                     $ noInteractive [ "Internal variable creation:"
-                                                     , "  Named: " ++ nm
-                                                     ]
+                               n = "__internal_sbv_" ++ nm
+                               v = (sv, n)
+                           modifyState st rinps (first ((q, v) :))
+                                     $ modifyIncState st rNewInps (\newInps -> case q of
+                                                                                 EX -> v : newInps
+                                                                                 -- I don't think the following can actually happen
+                                                                                 -- but just be safe:
+                                                                                 ALL  -> noInteractive [ "Internal universally quantified variable creation:"
+                                                                                                       , "  Named: " ++ nm
+                                                                                                       ])
                            return sv
 {-# INLINE internalVariable #-}
 
@@ -1006,31 +1093,41 @@
   = do -- Adding a kind to the incState is tricky; we only need to add it
        --     *    If it's an uninterpreted sort that's not already in the general state
        --     * OR If it's a tuple-sort whose cardinality isn't already in the general state
+       --     * OR If it's a list that's not already in the general state (so we can send the flatten commands)
 
        existingKinds <- readIORef (rUsedKinds st)
 
        modifyState st rUsedKinds (Set.insert k) $ do
 
+                          -- Why do we discriminate here? Because the incremental context is sensitive to the
+                          -- order: In particular, if an uninterpreted kind is already in there, we don't
+                          -- want to re-add because double-declaration would be wrong. See 'cvtInc' for details.
                           let needsAdding = case k of
                                               KUninterpreted{} -> k `notElem` existingKinds
+                                              KList{}          -> k `notElem` existingKinds
                                               KTuple nks       -> length nks `notElem` [length oks | KTuple oks <- Set.toList existingKinds]
+                                              KMaybe{}         -> k `notElem` existingKinds
+                                              KEither{}        -> k `notElem` existingKinds
                                               _                -> False
 
                           when needsAdding $ modifyIncState st rNewKinds (Set.insert k)
 
        -- Don't forget to register subkinds!
        case k of
-         KBool          {}  -> return ()
-         KBounded       {}  -> return ()
-         KUnbounded     {}  -> return ()
-         KReal          {}  -> return ()
-         KUninterpreted {}  -> return ()
-         KFloat         {}  -> return ()
-         KDouble        {}  -> return ()
-         KChar          {}  -> return ()
-         KString        {}  -> return ()
-         KList          ek  -> registerKind st ek
-         KTuple         eks -> mapM_ (registerKind st) eks
+         KBool          {}    -> return ()
+         KBounded       {}    -> return ()
+         KUnbounded     {}    -> return ()
+         KReal          {}    -> return ()
+         KUninterpreted {}    -> return ()
+         KFloat         {}    -> return ()
+         KDouble        {}    -> return ()
+         KChar          {}    -> return ()
+         KString        {}    -> return ()
+         KList          ek    -> registerKind st ek
+         KSet           ek    -> registerKind st ek
+         KTuple         eks   -> mapM_ (registerKind st) eks
+         KMaybe         ke    -> registerKind st ke
+         KEither        k1 k2 -> mapM_ (registerKind st) [k1, k2]
 
 -- | Register a new label with the system, making sure they are unique and have no '|'s in them
 registerLabel :: String -> State -> String -> IO ()
@@ -1054,9 +1151,11 @@
 newConst st c = do
   constMap <- readIORef (rconstMap st)
   case c `Map.lookup` constMap of
+    -- NB. Unlike in 'newExpr', we don't have to make sure the returned sv
+    -- has the kind we asked for, because the constMap stores the full CV
+    -- which already has a kind field in it.
     Just sv -> return sv
-    Nothing -> do let k = kindOf c
-                  (sv, _) <- newSV st k
+    Nothing -> do (sv, _) <- newSV st (kindOf c)
                   let ins = Map.insert c sv
                   modifyState st rconstMap ins $ modifyIncState st rNewConsts ins
                   return sv
@@ -1080,12 +1179,17 @@
    let e = reorder app
    exprMap <- readIORef (rexprMap st)
    case e `Map.lookup` exprMap of
-     Just sv -> return sv
-     Nothing -> do (sv, _) <- newSV st k
-                   let append (SBVPgm xs) = SBVPgm (xs S.|> (sv, e))
-                   modifyState st spgm append $ modifyIncState st rNewAsgns append
-                   modifyState st rexprMap (Map.insert e sv) (return ())
-                   return sv
+     -- NB. Check to make sure that the kind of the hash-consed value
+     -- is the same kind as we're requesting. This might look unnecessary,
+     -- at first, but `svSign` and `svUnsign` rely on this as we can
+     -- get the same expression but at a different type. See
+     -- <http://github.com/GaloisInc/cryptol/issues/566> as an example.
+     Just sv | kindOf sv == k -> return sv
+     _                        -> do (sv, _) <- newSV st k
+                                    let append (SBVPgm xs) = SBVPgm (xs S.|> (sv, e))
+                                    modifyState st spgm append $ modifyIncState st rNewAsgns append
+                                    modifyState st rexprMap (Map.insert e sv) (return ())
+                                    return sv
 {-# INLINE newExpr #-}
 
 -- | Convert a symbolic value to an internal SV
@@ -1198,45 +1302,81 @@
                        let nm = fromMaybe internalName mbNm
                        introduceUserName st isTracker nm k q sv
 
-            mkC   = do cv <- randomCV k
-                       do registerKind st k
-                          modifyState st rCInfo ((fromMaybe "_" mbNm, cv):) (return ())
-                       return $ SVal k (Left cv)
+            mkC cv = do registerKind st k
+                        modifyState st rCInfo ((fromMaybe "_" mbNm, cv):) (return ())
+                        return $ SVal k (Left cv)
 
         case (mbQ, rm) of
-          (Just q,  SMTMode{}        ) -> mkS q
-          (Nothing, SMTMode _ isSAT _) -> mkS (if isSAT then EX else ALL)
+          (Just q,  SMTMode{}          ) -> mkS q
+          (Nothing, SMTMode _ _ isSAT _) -> mkS (if isSAT then EX else ALL)
 
-          (Just EX, CodeGen{})         -> disallow "Existentially quantified variables"
-          (_      , CodeGen)           -> noUI $ mkS ALL  -- code generation, pick universal
+          (Just EX, CodeGen{})           -> disallow "Existentially quantified variables"
+          (_      , CodeGen)             -> noUI $ mkS ALL  -- code generation, pick universal
 
-          (Just EX,  Concrete{})       -> disallow "Existentially quantified variables"
-          (_      ,  Concrete{})       -> noUI mkC
+          (Just EX, Concrete Nothing)    -> disallow "Existentially quantified variables"
+          (_      , Concrete Nothing)    -> noUI (randomCV k >>= mkC)
 
--- | Introduce a new user name. We die if repeated.
+          -- Model validation:
+          (_      , Concrete (Just (_isSat, env))) ->
+                        let bad why conc = error $ unlines [ ""
+                                                           , "*** Data.SBV: " ++ why
+                                                           , "***"
+                                                           , "***   To turn validation off, use `cfg{validateModel = False}`"
+                                                           , "***"
+                                                           , "*** " ++ conc ++ "."
+                                                           ]
+
+                            cant   = "Validation engine is not capable of handling this case. Failed to validate"
+                            report = "Please report this as a bug in SBV!"
+
+                        in if isUninterpreted k
+                           then bad ("Cannot validate models in the presence of uninterpeted kinds, saw: " ++ show k) cant
+                           else do (sv, internalName) <- newSV st k
+
+                                   let nm = fromMaybe internalName mbNm
+                                       nsv = (sv, nm)
+
+                                       cv = case [(q, v) | ((q, nsv'), v) <- env, nsv == nsv'] of
+                                              []              -> bad ("Cannot locate variable: " ++ show nsv) report
+                                              [(ALL, _)]      -> bad ("Cannot validate models in the presence of universally quantified variable " ++ show (snd nsv)) cant
+                                              [(EX, Nothing)] -> bad ("Cannot locate model value of variable: " ++ show (snd nsv)) report
+                                              [(EX, Just c)]  -> c
+                                              r               -> bad (   "Found multiple matching values for variable: " ++ show nsv
+                                                                      ++ "\n*** " ++ show r) report
+
+                                   mkC cv
+
+-- | Introduce a new user name. We simply append a suffix if we have seen this variable before.
 introduceUserName :: State -> Bool -> String -> Kind -> Quantifier -> SV -> IO SVal
-introduceUserName st isTracker nm k q sv = do
+introduceUserName st isTracker nmOrig k q sv = do
         (is, ints) <- readIORef (rinps st)
-        if nm `elem` [n | (_, (_, n)) <- is] ++ [n | (_, n) <- ints]
-           then error $ "SBV: Repeated user given name: " ++ show nm ++ ". Please use unique names."
-           else if isTracker && q == ALL
-                then error $ "SBV: Impossible happened! A universally quantified tracker variable is being introduced: " ++ show nm
-                else do let newInp olds = case q of
-                                           EX  -> (sv, nm) : olds
-                                           ALL -> noInteractive [ "Adding a new universally quantified variable: "
-                                                                , "  Name      : " ++ show nm
-                                                                , "  Kind      : " ++ show k
-                                                                , "  Quantifier: Universal"
-                                                                , "  Node      : " ++ show sv
-                                                                , "Only existential variables are supported in query mode."
-                                                                ]
-                        if isTracker
-                           then modifyState st rinps (second ((:) (sv, nm)))
-                                          $ noInteractive ["Adding a new tracker variable in interactive mode: " ++ show nm]
-                           else modifyState st rinps (first ((:) (q, (sv, nm))))
-                                          $ modifyIncState st rNewInps newInp
-                        return $ SVal k $ Right $ cache (const (return sv))
 
+        let old = [n | (_, (_, n)) <- is] ++ [n | (_, n) <- ints]
+            nm  = mkUnique nmOrig old
+
+        if isTracker && q == ALL
+           then error $ "SBV: Impossible happened! A universally quantified tracker variable is being introduced: " ++ show nm
+           else do let newInp olds = case q of
+                                      EX  -> (sv, nm) : olds
+                                      ALL -> noInteractive [ "Adding a new universally quantified variable: "
+                                                           , "  Name      : " ++ show nm
+                                                           , "  Kind      : " ++ show k
+                                                           , "  Quantifier: Universal"
+                                                           , "  Node      : " ++ show sv
+                                                           , "Only existential variables are supported in query mode."
+                                                           ]
+                   if isTracker
+                      then modifyState st rinps (second ((:) (sv, nm)))
+                                     $ noInteractive ["Adding a new tracker variable in interactive mode: " ++ show nm]
+                      else modifyState st rinps (first ((:) (q, (sv, nm))))
+                                     $ modifyIncState st rNewInps newInp
+                   return $ SVal k $ Right $ cache (const (return sv))
+
+   where -- The following can be rather slow if we keep reusing the same prefix, but I doubt it'll be a problem in practice
+         -- Also, the following will fail if we span the range of integers without finding a match, but your computer would
+         -- die way ahead of that happening if that's the case!
+         mkUnique prefix names = head $ dropWhile (`elem` names) (prefix : [prefix ++ "_" ++ show i | i <- [(0::Int)..]])
+
 -- | Generalization of 'Data.SBV.addAxiom'
 addAxiom :: MonadSymbolic m => String -> [String] -> m ()
 addAxiom nm ax = do
@@ -1272,7 +1412,7 @@
      faiCache  <- newIORef IMap.empty
      usedKinds <- newIORef Set.empty
      usedLbls  <- newIORef Set.empty
-     cstrs     <- newIORef []
+     cstrs     <- newIORef S.empty
      smtOpts   <- newIORef []
      optGoals  <- newIORef []
      asserts   <- newIORef []
@@ -1344,20 +1484,21 @@
 
    traceVals   <- reverse <$> readIORef cInfo
    observables <- reverse <$> readIORef observes
-   extraCstrs  <- reverse <$> readIORef cstrs
+   extraCstrs  <- readIORef cstrs
    assertions  <- reverse <$> readIORef asserts
 
    return $ Result knds traceVals observables cgMap inpsO cnsts tbls arrs unint axs (SBVPgm rpgm) extraCstrs assertions outsO
 
 -- | Generalization of 'Data.SBV.addNewSMTOption'
 addNewSMTOption :: MonadSymbolic m => SMTOption -> m ()
-addNewSMTOption o =  do st <- symbolicEnv
-                        liftIO $ modifyState st rSMTOptions (o:) (return ())
+addNewSMTOption o = do st <- symbolicEnv
+                       liftIO $ modifyState st rSMTOptions (o:) (return ())
 
 -- | Generalization of 'Data.SBV.imposeConstraint'
 imposeConstraint :: MonadSymbolic m => Bool -> [(String, String)] -> SVal -> m ()
 imposeConstraint isSoft attrs c = do st <- symbolicEnv
                                      rm <- liftIO $ readIORef (runMode st)
+
                                      case rm of
                                        CodeGen -> error "SBV: constraints are not allowed in code-generation"
                                        _       -> liftIO $ do mapM_ (registerLabel "Constraint" st) [nm | (":named",  nm) <- attrs]
@@ -1366,14 +1507,26 @@
 -- | Require a boolean condition to be true in the state. Only used for internal purposes.
 internalConstraint :: State -> Bool -> [(String, String)] -> SVal -> IO ()
 internalConstraint st isSoft attrs b = do v <- svToSV st b
-                                          unless (null attrs && v == trueSV) $
-                                                 modifyState st rConstraints ((isSoft, attrs, v):)
-                                                              $ noInteractive [ "Adding an internal " ++ soft ++ "constraint:"
-                                                                              , "  Named: " ++ fromMaybe "<unnamed>" (listToMaybe [nm | (":named", nm) <- attrs])
-                                                                              ]
-    where soft | isSoft = "soft-"
-               | True   = ""
 
+                                          rm <- liftIO $ readIORef (runMode st)
+
+                                          -- Are we running validation? If so, we always want to
+                                          -- add the constraint for debug purposes. Otherwie
+                                          -- we only add it if it's interesting; i.e., not directly
+                                          -- true or has some attributes.
+                                          let isValidating = case rm of
+                                                               SMTMode _ _ _ cfg -> validateModel cfg
+                                                               CodeGen           -> False
+                                                               Concrete Nothing  -> False
+                                                               Concrete (Just _) -> True   -- The case when we *are* running the validation
+
+                                          let c           = (isSoft, attrs, v)
+                                              interesting = v /= trueSV || not (null attrs)
+
+                                          when (isValidating || interesting) $
+                                               modifyState st rConstraints (S.|> c)
+                                                            $ modifyIncState st rNewConstraints (S.|> c)
+
 -- | Generalization of 'Data.SBV.addSValOptGoal'
 addSValOptGoal :: MonadSymbolic m => Objective SVal -> m ()
 addSValOptGoal obj = do st <- symbolicEnv
@@ -1518,31 +1671,35 @@
 instance NFData SVal         where rnf (SVal x y) = rnf x `seq` rnf y `seq` ()
 
 instance NFData SMTResult where
-  rnf Unsatisfiable{}      = ()
-  rnf (Satisfiable _   xs) = rnf xs `seq` ()
-  rnf (SatExtField _   xs) = rnf xs `seq` ()
-  rnf (Unknown _       xs) = rnf xs `seq` ()
-  rnf (ProofError _    xs) = rnf xs `seq` ()
+  rnf (Unsatisfiable _ xs   ) = rnf xs
+  rnf (Satisfiable _   xs   ) = rnf xs `seq` ()
+  rnf (SatExtField _   xs   ) = rnf xs `seq` ()
+  rnf (Unknown _       xs   ) = rnf xs `seq` ()
+  rnf (ProofError _    xs mr) = rnf xs `seq` rnf mr `seq` ()
 
 instance NFData SMTModel where
-  rnf (SMTModel objs assocs) = rnf objs `seq` rnf assocs `seq` ()
+  rnf (SMTModel objs bndgs assocs uifuns) = rnf objs `seq` rnf bndgs `seq` rnf assocs `seq` rnf uifuns `seq` ()
 
 instance NFData SMTScript where
   rnf (SMTScript b m) = rnf b `seq` rnf m `seq` ()
 
 -- | Translation tricks needed for specific capabilities afforded by each solver
 data SolverCapabilities = SolverCapabilities {
-         supportsQuantifiers        :: Bool           -- ^ Support for SMT-Lib2 style quantifiers?
-       , supportsUninterpretedSorts :: Bool           -- ^ Support for SMT-Lib2 style uninterpreted-sorts
-       , supportsUnboundedInts      :: Bool           -- ^ Support for unbounded integers?
-       , supportsReals              :: Bool           -- ^ Support for reals?
+         supportsQuantifiers        :: Bool           -- ^ Supports SMT-Lib2 style quantifiers?
+       , supportsUninterpretedSorts :: Bool           -- ^ Supports SMT-Lib2 style uninterpreted-sorts
+       , supportsUnboundedInts      :: Bool           -- ^ Supports unbounded integers?
+       , supportsReals              :: Bool           -- ^ Supports reals?
        , supportsApproxReals        :: Bool           -- ^ Supports printing of approximations of reals?
-       , supportsIEEE754            :: Bool           -- ^ Support for floating point numbers?
-       , supportsOptimization       :: Bool           -- ^ Support for optimization routines?
-       , supportsPseudoBooleans     :: Bool           -- ^ Support for pseudo-boolean operations?
-       , supportsCustomQueries      :: Bool           -- ^ Support for interactive queries per SMT-Lib?
-       , supportsGlobalDecls        :: Bool           -- ^ Support for global decls, needed for push-pop.
-       , supportsFlattenedSequences :: Maybe [String] -- ^ Supports flattened sequence output, with given config lines
+       , supportsIEEE754            :: Bool           -- ^ Supports floating point numbers?
+       , supportsSets               :: Bool           -- ^ Supports set operations?
+       , supportsOptimization       :: Bool           -- ^ Supports optimization routines?
+       , supportsPseudoBooleans     :: Bool           -- ^ Supports pseudo-boolean operations?
+       , supportsCustomQueries      :: Bool           -- ^ Supports interactive queries per SMT-Lib?
+       , supportsGlobalDecls        :: Bool           -- ^ Supports global declarations? (Needed for push-pop.)
+       , supportsDataTypes          :: Bool           -- ^ Supports datatypes?
+       , supportsDTConstructorSigs  :: Bool           -- ^ Supports full ascription on data-type constructors? (CVC4 and z3 differ!)
+       , supportsDTAccessorSigs     :: Bool           -- ^ Supports full ascription on data-type accessor?     (CVC4 and z3 differ!)
+       , supportsFlattenedModels    :: Maybe [String] -- ^ Supports flattened model output? (With given config lines.)
        }
 
 -- | Rounding mode to be used for the IEEE floating-point operations.
@@ -1581,20 +1738,24 @@
 -- The 'printBase' field can be used to print numbers in base 2, 10, or 16. If base 2 or 16 is used, then floating-point values will
 -- be printed in their internal memory-layout format as well, which can come in handy for bit-precise analysis.
 data SMTConfig = SMTConfig {
-         verbose             :: Bool           -- ^ Debug mode
-       , timing              :: Timing         -- ^ Print timing information on how long different phases took (construction, solving, etc.)
-       , printBase           :: Int            -- ^ Print integral literals in this base (2, 10, and 16 are supported.)
-       , printRealPrec       :: Int            -- ^ Print algebraic real values with this precision. (SReal, default: 16)
-       , satCmd              :: String         -- ^ Usually "(check-sat)". However, users might tweak it based on solver characteristics.
-       , allSatMaxModelCount :: Maybe Int      -- ^ In an allSat call, return at most this many models. If nothing, return all.
-       , isNonModelVar       :: String -> Bool -- ^ When constructing a model, ignore variables whose name satisfy this predicate. (Default: (const False), i.e., don't ignore anything)
-       , transcript          :: Maybe FilePath -- ^ If Just, the entire interaction will be recorded as a playable file (for debugging purposes mostly)
-       , smtLibVersion       :: SMTLibVersion  -- ^ What version of SMT-lib we use for the tool
-       , solver              :: SMTSolver      -- ^ The actual SMT solver.
-       , roundingMode        :: RoundingMode   -- ^ Rounding mode to use for floating-point conversions
-       , solverSetOptions    :: [SMTOption]    -- ^ Options to set as we start the solver
-       , ignoreExitCode      :: Bool           -- ^ If true, we shall ignore the exit code upon exit. Otherwise we require ExitSuccess.
-       , redirectVerbose     :: Maybe FilePath -- ^ Redirect the verbose output to this file if given. If Nothing, stdout is implied.
+         verbose                :: Bool           -- ^ Debug mode
+       , timing                 :: Timing         -- ^ Print timing information on how long different phases took (construction, solving, etc.)
+       , printBase              :: Int            -- ^ Print integral literals in this base (2, 10, and 16 are supported.)
+       , printRealPrec          :: Int            -- ^ Print algebraic real values with this precision. (SReal, default: 16)
+       , satCmd                 :: String         -- ^ Usually "(check-sat)". However, users might tweak it based on solver characteristics.
+       , allSatMaxModelCount    :: Maybe Int      -- ^ In a 'Data.SBV.allSat' call, return at most this many models. If nothing, return all.
+       , allSatPrintAlong       :: Bool           -- ^ In a 'Data.SBV.allSat' call, print models as they are found.
+       , satTrackUFs            :: Bool           -- ^ In a 'Data.SBV.sat' call, should we try to extract values of uninterpreted functions?
+       , isNonModelVar          :: String -> Bool -- ^ When constructing a model, ignore variables whose name satisfy this predicate. (Default: (const False), i.e., don't ignore anything)
+       , validateModel          :: Bool           -- ^ If set, SBV will attempt to validate the model it gets back from the solver.
+       , transcript             :: Maybe FilePath -- ^ If Just, the entire interaction will be recorded as a playable file (for debugging purposes mostly)
+       , smtLibVersion          :: SMTLibVersion  -- ^ What version of SMT-lib we use for the tool
+       , solver                 :: SMTSolver      -- ^ The actual SMT solver.
+       , allowQuantifiedQueries :: Bool           -- ^ Should we permit use of quantifiers in the query mode? (Default: False. See <http://github.com/LeventErkok/sbv/issues/459> for why.)
+       , roundingMode           :: RoundingMode   -- ^ Rounding mode to use for floating-point conversions
+       , solverSetOptions       :: [SMTOption]    -- ^ Options to set as we start the solver
+       , ignoreExitCode         :: Bool           -- ^ If true, we shall ignore the exit code upon exit. Otherwise we require ExitSuccess.
+       , redirectVerbose        :: Maybe FilePath -- ^ Redirect the verbose output to this file if given. If Nothing, stdout is implied.
        }
 
 -- We're just seq'ing top-level here, it shouldn't really matter. (i.e., no need to go deeper.)
@@ -1603,8 +1764,12 @@
 
 -- | A model, as returned by a solver
 data SMTModel = SMTModel {
-        modelObjectives :: [(String, GeneralizedCV)]  -- ^ Mapping of symbolic values to objective values.
-     ,  modelAssocs     :: [(String, CV)]             -- ^ Mapping of symbolic values to constants.
+       modelObjectives :: [(String, GeneralizedCV)]                       -- ^ Mapping of symbolic values to objective values.
+     , modelBindings   :: Maybe [((Quantifier, NamedSymVar), Maybe CV)]   -- ^ Mapping of input variables as reported by the solver. Only collected if model validation is requested.
+     , modelAssocs     :: [(String, CV)]                                  -- ^ Mapping of symbolic values to constants.
+     , modelUIFuns     :: [(String, (SBVType, ([([CV], CV)], CV)))]       -- ^ Mapping of uninterpreted functions to association lists in the model.
+                                                                          -- Note that an uninterpreted constant (function of arity 0) will be stored
+                                                                          -- in the 'modelAssocs' field.
      }
      deriving Show
 
@@ -1613,11 +1778,11 @@
 -- and build layers of results, if needed. For ordinary uses of the library,
 -- this type should not be needed, instead use the accessor functions on
 -- it. (Custom Show instances and model extractors.)
-data SMTResult = Unsatisfiable SMTConfig (Maybe [String]) -- ^ Unsatisfiable. If unsat-cores are enabled, they will be returned in the second parameter.
-               | Satisfiable   SMTConfig SMTModel         -- ^ Satisfiable with model
-               | SatExtField   SMTConfig SMTModel         -- ^ Prover returned a model, but in an extension field containing Infinite/epsilon
-               | Unknown       SMTConfig SMTReasonUnknown -- ^ Prover returned unknown, with the given reason
-               | ProofError    SMTConfig [String]         -- ^ Prover errored out
+data SMTResult = Unsatisfiable SMTConfig (Maybe [String])            -- ^ Unsatisfiable. If unsat-cores are enabled, they will be returned in the second parameter.
+               | Satisfiable   SMTConfig SMTModel                    -- ^ Satisfiable with model
+               | SatExtField   SMTConfig SMTModel                    -- ^ Prover returned a model, but in an extension field containing Infinite/epsilon
+               | Unknown       SMTConfig SMTReasonUnknown            -- ^ Prover returned unknown, with the given reason
+               | ProofError    SMTConfig [String] (Maybe SMTResult)  -- ^ Prover errored out, with possibly a bogus result
 
 -- | A script, to be passed to the solver.
 data SMTScript = SMTScript {
@@ -1655,6 +1820,11 @@
 -- | Query execution context
 data QueryContext = QueryInternal       -- ^ Triggered from inside SBV
                   | QueryExternal       -- ^ Triggered from user code
+
+-- | Show instance for 'QueryContext', for debugging purposes
+instance Show QueryContext where
+   show QueryInternal = "Internal Query"
+   show QueryExternal = "User Query"
 
 {-# ANN type FPOp ("HLint: ignore Use camelCase" :: String) #-}
 {-# ANN type PBOp ("HLint: ignore Use camelCase" :: String) #-}
diff --git a/Data/SBV/Dynamic.hs b/Data/SBV/Dynamic.hs
--- a/Data/SBV/Dynamic.hs
+++ b/Data/SBV/Dynamic.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Dynamic
--- Author    : Brian Huffman
+-- Copyright : (c) Brian Huffman
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -63,6 +63,7 @@
   , svToWord1, svFromWord1, svTestBit, svSetBit
   , svShiftLeft, svShiftRight
   , svRotateLeft, svRotateRight
+  , svBarrelRotateLeft, svBarrelRotateRight
   , svWordFromBE, svWordFromLE
   , svBlastLE, svBlastBE
   -- ** Conditionals: Mergeable values
diff --git a/Data/SBV/Either.hs b/Data/SBV/Either.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Either.hs
@@ -0,0 +1,273 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Either
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Symbolic coproduct, symbolic version of Haskell's 'Either' type.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE TypeOperators       #-}
+
+module Data.SBV.Either (
+    -- * Constructing sums
+      sLeft, sRight, liftEither
+    -- * Destructing sums
+    , either
+    -- * Mapping functions
+    , bimap, first, second
+    -- * Scrutinizing branches of a sum
+    , isLeft, isRight, fromLeft, fromRight
+  ) where
+
+import           Prelude hiding (either)
+import qualified Prelude
+
+import Data.Proxy (Proxy(Proxy))
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model () -- instances only
+
+-- For doctest use only
+--
+-- $setup
+-- >>> import Data.SBV.Core.Model
+-- >>> import Data.SBV.Provers.Prover
+
+-- | Construct an @SEither a b@ from an @SBV a@
+--
+-- >>> sLeft 3 :: SEither Integer Bool
+-- Left 3 :: SEither Integer Bool
+sLeft :: forall a b. (SymVal a, SymVal b) => SBV a -> SEither a b
+sLeft sa
+  | Just a <- unliteral sa
+  = literal (Left a)
+  | True
+  = SBV $ SVal k $ Right $ cache res
+  where k1 = kindOf (Proxy @a)
+        k2 = kindOf (Proxy @b)
+        k  = KEither k1 k2
+
+        res st = do asv <- sbvToSV st sa
+                    newExpr st k $ SBVApp (EitherConstructor k1 k2 False) [asv]
+
+-- | Return 'sTrue' if the given symbolic value is 'Left', 'sFalse' otherwise
+--
+-- >>> isLeft (sLeft 3 :: SEither Integer Bool)
+-- True
+-- >>> isLeft (sRight sTrue :: SEither Integer Bool)
+-- False
+isLeft :: (SymVal a, SymVal b) => SEither a b -> SBV Bool
+isLeft = either (const sTrue) (const sFalse)
+
+-- | Construct an @SEither a b@ from an @SBV b@
+--
+-- >>> sRight sFalse :: SEither Integer Bool
+-- Right False :: SEither Integer Bool
+sRight :: forall a b. (SymVal a, SymVal b) => SBV b -> SEither a b
+sRight sb
+  | Just b <- unliteral sb
+  = literal (Right b)
+  | True
+  = SBV $ SVal k $ Right $ cache res
+  where k1 = kindOf (Proxy @a)
+        k2 = kindOf (Proxy @b)
+        k  = KEither k1 k2
+
+        res st = do bsv <- sbvToSV st sb
+                    newExpr st k $ SBVApp (EitherConstructor k1 k2 True) [bsv]
+
+-- | Return 'sTrue' if the given symbolic value is 'Right', 'sFalse' otherwise
+--
+-- >>> isRight (sLeft 3 :: SEither Integer Bool)
+-- False
+-- >>> isRight (sRight sTrue :: SEither Integer Bool)
+-- True
+isRight :: (SymVal a, SymVal b) => SEither a b -> SBV Bool
+isRight = either (const sFalse) (const sTrue)
+
+-- | Construct an @SEither a b@ from an @Either (SBV a) (SBV b)@
+--
+-- >>> liftEither (Left 3 :: Either SInteger SBool)
+-- Left 3 :: SEither Integer Bool
+-- >>> liftEither (Right sTrue :: Either SInteger SBool)
+-- Right True :: SEither Integer Bool
+liftEither :: (SymVal a, SymVal b) => Either (SBV a) (SBV b) -> SEither a b
+liftEither = Prelude.either sLeft sRight
+
+-- | Case analysis for symbolic 'Either's. If the value 'isLeft', apply the
+-- first function; if it 'isRight', apply the second function.
+--
+-- >>> either (*2) (*3) (sLeft 3)
+-- 6 :: SInteger
+-- >>> either (*2) (*3) (sRight 3)
+-- 9 :: SInteger
+-- >>> let f = uninterpret "f" :: SInteger -> SInteger
+-- >>> let g = uninterpret "g" :: SInteger -> SInteger
+-- >>> prove $ \x -> either f g (sLeft x) .== f x
+-- Q.E.D.
+-- >>> prove $ \x -> either f g (sRight x) .== g x
+-- Q.E.D.
+either :: forall a b c. (SymVal a, SymVal b, SymVal c)
+       => (SBV a -> SBV c)
+       -> (SBV b -> SBV c)
+       -> SEither a b
+       -> SBV c
+either brA brB sab
+  | Just (Left  a) <- unliteral sab
+  = brA $ literal a
+  | Just (Right b) <- unliteral sab
+  = brB $ literal b
+  | True
+  = SBV $ SVal kc $ Right $ cache res
+  where ka = kindOf (Proxy @a)
+        kb = kindOf (Proxy @b)
+        kc = kindOf (Proxy @c)
+
+        res st = do abv <- sbvToSV st sab
+
+                    let leftVal  = SBV $ SVal ka $ Right $ cache $ \_ -> newExpr st ka $ SBVApp (EitherAccess False) [abv]
+                        rightVal = SBV $ SVal kb $ Right $ cache $ \_ -> newExpr st kb $ SBVApp (EitherAccess True)  [abv]
+
+                        leftRes  = brA leftVal
+                        rightRes = brB rightVal
+
+                    br1 <- sbvToSV st leftRes
+                    br2 <- sbvToSV st rightRes
+
+                    --  Which branch are we in? Return the appropriate value:
+                    onLeft <- newExpr st KBool $ SBVApp (EitherIs ka kb False) [abv]
+                    newExpr st kc $ SBVApp Ite [onLeft, br1, br2]
+
+-- | Map over both sides of a symbolic 'Either' at the same time
+--
+-- >>> let f = uninterpret "f" :: SInteger -> SInteger
+-- >>> let g = uninterpret "g" :: SInteger -> SInteger
+-- >>> prove $ \x -> fromLeft (bimap f g (sLeft x)) .== f x
+-- Q.E.D.
+-- >>> prove $ \x -> fromRight (bimap f g (sRight x)) .== g x
+-- Q.E.D.
+bimap :: forall a b c d.  (SymVal a, SymVal b, SymVal c, SymVal d)
+      => (SBV a -> SBV b)
+      -> (SBV c -> SBV d)
+      -> SEither a c
+      -> SEither b d
+bimap brA brC = either (sLeft . brA) (sRight . brC)
+
+-- | Map over the left side of an 'Either'
+--
+-- >>> let f = uninterpret "f" :: SInteger -> SInteger
+-- >>> prove $ \x -> first f (sLeft x :: SEither Integer Integer) .== sLeft (f x)
+-- Q.E.D.
+-- >>> prove $ \x -> first f (sRight x :: SEither Integer Integer) .== sRight x
+-- Q.E.D.
+first :: (SymVal a, SymVal b, SymVal c) => (SBV a -> SBV b) -> SEither a c -> SEither b c
+first f = bimap f id
+
+-- | Map over the right side of an 'Either'
+--
+-- >>> let f = uninterpret "f" :: SInteger -> SInteger
+-- >>> prove $ \x -> second f (sRight x :: SEither Integer Integer) .== sRight (f x)
+-- Q.E.D.
+-- >>> prove $ \x -> second f (sLeft x :: SEither Integer Integer) .== sLeft x
+-- Q.E.D.
+second :: (SymVal a, SymVal b, SymVal c) => (SBV b -> SBV c) -> SEither a b -> SEither a c
+second = bimap id
+
+-- | Return the value from the left component. The behavior is undefined if
+-- passed a right value.
+--
+-- >>> fromLeft (sLeft (literal 'a') :: SEither Char Integer)
+-- 'a' :: SChar
+-- >>> prove $ \x -> fromLeft (sLeft x :: SEither Char Integer) .== (x :: SChar)
+-- Q.E.D.
+-- >>> sat $ \x -> x .== (fromLeft (sRight 4 :: SEither Char Integer))
+-- Satisfiable. Model:
+--   s0 = '\NUL' :: Char
+--
+-- Note how we get a satisfying assignment in the last case: The behavior
+-- is unspecified, thus the SMT solver picks whatever satisfies the
+-- constraints, if there is one.
+fromLeft :: forall a b. (SymVal a, SymVal b) => SEither a b -> SBV a
+fromLeft sab
+  | Just (Left a) <- unliteral sab
+  = literal a
+  | True
+  = SBV $ SVal ka $ Right $ cache res
+  where ka      = kindOf (Proxy @a)
+        kb      = kindOf (Proxy @b)
+        kEither = KEither ka kb
+
+        -- We play the usual trick here of creating a left value and asserting equivalence
+        -- under implication. This will be underspecified as required should the value
+        -- received be a right thing.
+        res st = do -- grab an internal variable and make a left out of it
+                    e  <- internalVariable st ka
+                    es <- newExpr st kEither (SBVApp (EitherConstructor ka kb False) [e])
+
+                    -- Create the condition that it is equal to the input
+                    ms <- sbvToSV st sab
+                    eq <- newExpr st KBool (SBVApp Equal [es, ms])
+
+                    -- Gotta make sure we do this only when input is not right
+                    caseRight <- sbvToSV st (isRight sab)
+                    require   <- newExpr st KBool (SBVApp Or [caseRight, eq])
+
+                    -- register the constraint:
+                    internalConstraint st False [] $ SVal KBool $ Right $ cache $ \_ -> return require
+
+                    -- We're good to go
+                    return e
+
+-- | Return the value from the right component. The behavior is undefined if
+-- passed a left value.
+--
+-- >>> fromRight (sRight (literal 'a') :: SEither Integer Char)
+-- 'a' :: SChar
+-- >>> prove $ \x -> fromRight (sRight x :: SEither Char Integer) .== (x :: SInteger)
+-- Q.E.D.
+-- >>> sat $ \x -> x .== (fromRight (sLeft (literal 'a') :: SEither Char Integer))
+-- Satisfiable. Model:
+--   s0 = 0 :: Integer
+--
+-- Note how we get a satisfying assignment in the last case: The behavior
+-- is unspecified, thus the SMT solver picks whatever satisfies the
+-- constraints, if there is one.
+fromRight :: forall a b. (SymVal a, SymVal b) => SEither a b -> SBV b
+fromRight sab
+  | Just (Right b) <- unliteral sab
+  = literal b
+  | True
+  = SBV $ SVal kb $ Right $ cache res
+  where ka      = kindOf (Proxy @a)
+        kb      = kindOf (Proxy @b)
+        kEither = KEither ka kb
+
+        -- We play the usual trick here of creating a right value and asserting equivalence
+        -- under implication. This will be underspecified as required should the value
+        -- received be a right thing.
+        res st = do -- grab an internal variable and make a right out of it
+                    e  <- internalVariable st kb
+                    es <- newExpr st kEither (SBVApp (EitherConstructor ka kb True) [e])
+
+                    -- Create the condition that it is equal to the input
+                    ms <- sbvToSV st sab
+                    eq <- newExpr st KBool (SBVApp Equal [es, ms])
+
+                    -- Gotta make sure we do this only when input is not left
+                    caseLeft <- sbvToSV st (isLeft sab)
+                    require  <- newExpr st KBool (SBVApp Or [caseLeft, eq])
+
+                    -- register the constraint:
+                    internalConstraint st False [] $ SVal KBool $ Right $ cache $ \_ -> return require
+
+                    -- We're good to go
+                    return e
+
+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Data/SBV/Internals.hs b/Data/SBV/Internals.hs
--- a/Data/SBV/Internals.hs
+++ b/Data/SBV/Internals.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Internals
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,11 +9,17 @@
 -- Low level functions to access the SBV infrastructure, for developers who
 -- want to build further tools on top of SBV. End-users of the library
 -- should not need to use this module.
+--
+-- NB. There are various coding invariants in SBV that are maintained
+-- throughout the code. Indiscriminate use of functions in this module
+-- can break those invariants. So, you are on your own if you do utilize
+-- the functions here. (Unfortunately, what exactly those invariants are
+-- is a very good but also a very difficult question to answer!)
 -----------------------------------------------------------------------------
 
 module Data.SBV.Internals (
   -- * Running symbolic programs /manually/
-    Result(..), SBVRunMode(..), IStage(..)
+    Result(..), SBVRunMode(..), IStage(..), QueryContext(..)
 
   -- * Solver capabilities
   , SolverCapabilities(..)
@@ -44,15 +50,16 @@
   , sendStringToSolver, sendRequestToSolver, retrieveResponseFromSolver
 
   -- * Defining new metrics
-  , addSValOptGoal
-
+  , addSValOptGoal, sFloatAsComparableSWord32, sDoubleAsComparableSWord64
   ) where
 
 import Control.Monad.IO.Class (MonadIO)
 
 import Data.SBV.Core.Data
 import Data.SBV.Core.Model      (genLiteral, genFromCV, genMkSymVar, liftQRem, liftDMod)
-import Data.SBV.Core.Symbolic   (IStage(..), MonadQuery, addSValOptGoal, registerKind)
+import Data.SBV.Core.Symbolic   (IStage(..), QueryContext(..), MonadQuery, addSValOptGoal, registerKind)
+
+import Data.SBV.Core.Floating   (sFloatAsComparableSWord32, sDoubleAsComparableSWord64)
 
 import Data.SBV.Compilers.C       (compileToC', compileToCLib')
 import Data.SBV.Compilers.CodeGen
diff --git a/Data/SBV/List.hs b/Data/SBV/List.hs
--- a/Data/SBV/List.hs
+++ b/Data/SBV/List.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.List
--- Author    : Joel Burget, Levent Erkok
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -22,14 +23,14 @@
         -- * Length, emptiness
           length, null
         -- * Deconstructing/Reconstructing
-        , head, tail, uncons, init, singleton, listToListAt, elemAt, (.!!), implode, concat, (.:), nil, (.++)
+        , head, tail, uncons, init, singleton, listToListAt, elemAt, (.!!), implode, concat, (.:), snoc, nil, (.++)
         -- * Containment
-        , isInfixOf, isSuffixOf, isPrefixOf
+        , elem, notElem, isInfixOf, isSuffixOf, isPrefixOf
         -- * Sublists
         , take, drop, subList, replace, indexOf, offsetIndexOf
         ) where
 
-import Prelude hiding (head, tail, init, length, take, drop, concat, null)
+import Prelude hiding (head, tail, init, length, take, drop, concat, null, elem, notElem)
 import qualified Prelude as P
 
 import Data.SBV.Core.Data hiding (StrOp(..))
@@ -72,7 +73,7 @@
   | Just cs <- unliteral l
   = literal (P.null cs)
   | True
-  = l .== literal []
+  = length l .== 0
 
 -- | @`head`@ returns the first element of a list. Unspecified if the list is empty.
 --
@@ -127,7 +128,7 @@
 -- Q.E.D.
 -- >>> sat $ \(l :: SList Word16) -> length l .>= 2 .&& listToListAt l 0 ./= listToListAt l (length l - 1)
 -- Satisfiable. Model:
---   s0 = [0,0,32] :: [Word16]
+--   s0 = [0,0,8192] :: [Word16]
 listToListAt :: SymVal a => SList a -> SInteger -> SList a
 listToListAt s offset = subList s offset 1
 
@@ -146,14 +147,27 @@
   = SBV (SVal kElem (Right (cache (y (l `listToListAt` i)))))
   where kElem = kindOf (Proxy @a)
         kSeq  = KList kElem
+
         -- This is trickier than it needs to be, but necessary since there's
         -- no SMTLib function to extract the element from a list. Instead,
         -- we form a singleton list, and assert that it is equivalent to
         -- the extracted value. See <http://github.com/Z3Prover/z3/issues/1302>
-        y si st = do e <- internalVariable st kElem
+        y si st = do -- grab an internal variable and make a unit list out of it
+                     e <- internalVariable st kElem
                      es <- newExpr st kSeq (SBVApp (SeqOp SeqUnit) [e])
-                     let esSBV = SBV (SVal kSeq (Right (cache (\_ -> return es))))
-                     internalConstraint st False [] $ unSBV $ length l .> i .=> esSBV .== si
+
+                     -- Create the condition that it is equal to si
+                     li <- sbvToSV st si
+                     eq <- newExpr st KBool (SBVApp Equal [es, li])
+
+                     -- Gotta make sure we do this only when length is at least > i
+                     caseTooShort <- sbvToSV st (length l .<= i)
+                     require      <- newExpr st KBool (SBVApp Or [caseTooShort, eq])
+
+                     -- register the constraint:
+                     internalConstraint st False [] $ SVal KBool $ Right $ cache $ \_ -> return require
+
+                     -- We're good to go:
                      return e
 
 -- | Short cut for 'elemAt'
@@ -182,6 +196,10 @@
 (.:) :: SymVal a => SBV a -> SList a -> SList a
 a .: as = singleton a .++ as
 
+-- | Append an element
+snoc :: SymVal a => SList a -> SBV a -> SList a
+as `snoc` a = as .++ singleton a
+
 -- | Empty list. This value has the property that it's the only list with length 0:
 --
 -- >>> prove $ \(l :: SList Integer) -> length l .== 0 .<=> l .== nil
@@ -200,13 +218,21 @@
 (.++) :: SymVal a => SList a -> SList a -> SList a
 (.++) = concat
 
+-- | @`elem` e l@. Does @l@ contain the element @e@?
+elem :: (Eq a, SymVal a) => SBV a -> SList a -> SBool
+e `elem` l = singleton e `isInfixOf` l
+
+-- | @`notElem` e l@. Does @l@ not contain the element @e@?
+notElem :: (Eq a, SymVal a) => SBV a -> SList a -> SBool
+e `notElem` l = sNot (e `elem` l)
+
 -- | @`isInfixOf` sub l@. Does @l@ contain the subsequence @sub@?
 --
 -- >>> prove $ \(l1 :: SList Integer) l2 l3 -> l2 `isInfixOf` (l1 .++ l2 .++ l3)
 -- Q.E.D.
 -- >>> prove $ \(l1 :: SList Integer) l2 -> l1 `isInfixOf` l2 .&& l2 `isInfixOf` l1 .<=> l1 .== l2
 -- Q.E.D.
-isInfixOf :: SymVal a => SList a -> SList a -> SBool
+isInfixOf :: (Eq a, SymVal a) => SList a -> SList a -> SBool
 sub `isInfixOf` l
   | isConcretelyEmpty sub
   = literal True
@@ -219,7 +245,7 @@
 -- Q.E.D.
 -- >>> prove $ \(l1 :: SList Integer) l2 -> l1 `isPrefixOf` l2 .=> subList l2 0 (length l1) .== l1
 -- Q.E.D.
-isPrefixOf :: SymVal a => SList a -> SList a -> SBool
+isPrefixOf :: (Eq a, SymVal a) => SList a -> SList a -> SBool
 pre `isPrefixOf` l
   | isConcretelyEmpty pre
   = literal True
@@ -232,7 +258,7 @@
 -- Q.E.D.
 -- >>> prove $ \(l1 :: SList Word16) l2 -> l1 `isSuffixOf` l2 .=> subList l2 (length l2 - length l1) (length l1) .== l1
 -- Q.E.D.
-isSuffixOf :: SymVal a => SList a -> SList a -> SBool
+isSuffixOf :: (Eq a, SymVal a) => SList a -> SList a -> SBool
 suf `isSuffixOf` l
   | isConcretelyEmpty suf
   = literal True
@@ -292,7 +318,7 @@
 -- Q.E.D.
 -- >>> prove $ \(l1 :: SList Integer) l2 l3 -> length l2 .> length l1 .=> replace l1 l2 l3 .== l1
 -- Q.E.D.
-replace :: SymVal a => SList a -> SList a -> SList a -> SList a
+replace :: (Eq a, SymVal a) => SList a -> SList a -> SList a -> SList a
 replace l src dst
   | Just b <- unliteral src, P.null b   -- If src is null, simply prepend
   = dst .++ l
@@ -315,11 +341,11 @@
 -- Q.E.D.
 -- >>> prove $ \(l :: SList Word16) i -> i .> 0 .&& i .< length l .=> indexOf l (subList l i 1) .== i
 -- Falsifiable. Counter-example:
---   s0 = [32,0,0] :: [Word16]
---   s1 =        2 :: Integer
+--   s0 = [2048,0,0,0,0,0] :: [Word16]
+--   s1 =                3 :: Integer
 -- >>> prove $ \(l1 :: SList Word16) l2 -> length l2 .> length l1 .=> indexOf l1 l2 .== -1
 -- Q.E.D.
-indexOf :: SymVal a => SList a -> SList a -> SInteger
+indexOf :: (Eq a, SymVal a) => SList a -> SList a -> SInteger
 indexOf s sub = offsetIndexOf s sub 0
 
 -- | @`offsetIndexOf` l sub offset@. Retrieves first position of @sub@ at or
@@ -331,7 +357,7 @@
 -- Q.E.D.
 -- >>> prove $ \(l :: SList Int8) sub i -> i .> length l .=> offsetIndexOf l sub i .== -1
 -- Q.E.D.
-offsetIndexOf :: SymVal a => SList a -> SList a -> SInteger -> SInteger
+offsetIndexOf :: (Eq a, SymVal a) => SList a -> SList a -> SInteger -> SInteger
 offsetIndexOf s sub offset
   | Just c <- unliteral s        -- a constant list
   , Just n <- unliteral sub      -- a constant search pattern
diff --git a/Data/SBV/Maybe.hs b/Data/SBV/Maybe.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Maybe.hs
@@ -0,0 +1,207 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Maybe
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Symbolic option type, symbolic version of Haskell's 'Maybe' type.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+{-# LANGUAGE TypeOperators       #-}
+
+module Data.SBV.Maybe (
+  -- * Constructing optional values
+    sJust, sNothing, liftMaybe
+  -- * Destructing optionals
+  , maybe
+  -- * Mapping functions
+  , map
+  -- * Scrutinizing the branches of an option
+  , isNothing, isJust, fromMaybe, fromJust
+  ) where
+
+import           Prelude hiding (maybe, map)
+import qualified Prelude
+
+import Data.Proxy (Proxy(Proxy))
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model () -- instances only
+
+-- For doctest use only
+--
+-- $setup
+-- >>> import Data.SBV.Core.Model
+-- >>> import Data.SBV.Provers.Prover
+
+-- | The symbolic 'Nothing'
+--
+-- >>> sNothing :: SMaybe Integer
+-- Nothing :: SMaybe Integer
+sNothing :: forall a. SymVal a => SMaybe a
+sNothing = SBV $ SVal k $ Left $ CV k $ CMaybe Nothing
+  where k = kindOf (Proxy @(Maybe a))
+
+-- | Check if the symbolic value is nothing.
+--
+-- >>> isNothing (sNothing :: SMaybe Integer)
+-- True
+-- >>> isNothing (sJust (literal "nope"))
+-- False
+isNothing :: SymVal a => SMaybe a -> SBool
+isNothing = maybe sTrue (const sFalse)
+
+-- | Construct an @SMaybe a@ from an @SBV a@
+--
+-- >>> sJust 3
+-- Just 3 :: SMaybe Integer
+sJust :: forall a. SymVal a => SBV a -> SMaybe a
+sJust sa
+  | Just a <- unliteral sa
+  = literal (Just a)
+  | True
+  = SBV $ SVal kMaybe $ Right $ cache res
+  where ka     = kindOf (Proxy @a)
+        kMaybe = KMaybe ka
+
+        res st = do asv <- sbvToSV st sa
+                    newExpr st kMaybe $ SBVApp (MaybeConstructor ka True) [asv]
+
+-- | Check if the symbolic value is not nothing.
+--
+-- >>> isJust (sNothing :: SMaybe Integer)
+-- False
+-- >>> isJust (sJust (literal "yep"))
+-- True
+-- >>> prove $ \x -> isJust (sJust (x :: SInteger))
+-- Q.E.D.
+isJust :: SymVal a => SMaybe a -> SBool
+isJust = maybe sFalse (const sTrue)
+
+-- | Return the value of an optional value. The default is returned if Nothing. Compare to 'fromJust'.
+--
+-- >>> fromMaybe 2 (sNothing :: SMaybe Integer)
+-- 2 :: SInteger
+-- >>> fromMaybe 2 (sJust 5 :: SMaybe Integer)
+-- 5 :: SInteger
+-- >>> prove $ \x -> fromMaybe x (sNothing :: SMaybe Integer) .== x
+-- Q.E.D.
+-- >>> prove $ \x -> fromMaybe (x+1) (sJust x :: SMaybe Integer) .== x
+-- Q.E.D.
+fromMaybe :: SymVal a => SBV a -> SMaybe a -> SBV a
+fromMaybe def = maybe def id
+
+-- | Return the value of an optional value. The behavior is undefined if
+-- passed Nothing. Compare to 'fromMaybe'.
+--
+-- >>> fromJust (sJust (literal 'a'))
+-- 'a' :: SChar
+-- >>> prove $ \x -> fromJust (sJust x) .== (x :: SChar)
+-- Q.E.D.
+-- >>> sat $ \x -> x .== (fromJust sNothing :: SChar)
+-- Satisfiable. Model:
+--   s0 = '\NUL' :: Char
+--
+-- Note how we get a satisfying assignment in the last case: The behavior
+-- is unspecified, thus the SMT solver picks whatever satisfies the
+-- constraints, if there is one.
+fromJust :: forall a. SymVal a => SMaybe a -> SBV a
+fromJust ma
+  | Just (Just x) <- unliteral ma
+  = literal x
+  | True
+  = SBV $ SVal ka $ Right $ cache res
+  where ka     = kindOf (Proxy @a)
+        kMaybe = KMaybe ka
+
+        -- We play the usual trick here of creating a just value
+        -- and asserting equivalence under implication. This will
+        -- be underspecified as required should the value
+        -- received be `Nothing`.
+        res st = do -- grab an internal variable and make a Maybe out of it
+                    e  <- internalVariable st ka
+                    es <- newExpr st kMaybe (SBVApp (MaybeConstructor ka True) [e])
+
+                    -- Create the condition that it is equal to the input
+                    ms <- sbvToSV st ma
+                    eq <- newExpr st KBool (SBVApp Equal [es, ms])
+
+                    -- Gotta make sure we do this only when input is not nothing
+                    caseNothing <- sbvToSV st (isNothing ma)
+                    require     <- newExpr st KBool (SBVApp Or [caseNothing, eq])
+
+                    -- register the constraint:
+                    internalConstraint st False [] $ SVal KBool $ Right $ cache $ \_ -> return require
+
+                    -- We're good to go:
+                    return e
+
+-- | Construct an @SMaybe a@ from a @Maybe (SBV a)@
+--
+-- >>> liftMaybe (Just (3 :: SInteger))
+-- Just 3 :: SMaybe Integer
+-- >>> liftMaybe (Nothing :: Maybe SInteger)
+-- Nothing :: SMaybe Integer
+liftMaybe :: SymVal a => Maybe (SBV a) -> SMaybe a
+liftMaybe = Prelude.maybe (literal Nothing) sJust
+
+-- | Map over the 'Just' side of a 'Maybe'
+--
+-- >>> prove $ \x -> fromJust (map (+1) (sJust x)) .== x+1
+-- Q.E.D.
+-- >>> let f = uninterpret "f" :: SInteger -> SBool
+-- >>> prove $ \x -> map f (sJust x) .== sJust (f x)
+-- Q.E.D.
+-- >>> map f sNothing .== sNothing
+-- True
+map :: forall a b.  (SymVal a, SymVal b)
+    => (SBV a -> SBV b)
+    -> SMaybe a
+    -> SMaybe b
+map f = maybe (literal Nothing) (sJust . f)
+
+-- | Case analysis for symbolic 'Maybe's. If the value 'isNothing', return the
+-- default value; if it 'isJust', apply the function.
+--
+-- >>> maybe 0 (`sMod` 2) (sJust (3 :: SInteger))
+-- 1 :: SInteger
+-- >>> maybe 0 (`sMod` 2) (sNothing :: SMaybe Integer)
+-- 0 :: SInteger
+-- >>> let f = uninterpret "f" :: SInteger -> SBool
+-- >>> prove $ \x d -> maybe d f (sJust x) .== f x
+-- Q.E.D.
+-- >>> prove $ \d -> maybe d f sNothing .== d
+-- Q.E.D.
+maybe :: forall a b.  (SymVal a, SymVal b)
+      => SBV b
+      -> (SBV a -> SBV b)
+      -> SMaybe a
+      -> SBV b
+maybe brNothing brJust ma
+  | Just (Just a) <- unliteral ma
+  = brJust (literal a)
+  | Just Nothing  <- unliteral ma
+  = brNothing
+  | True
+  = SBV $ SVal kb $ Right $ cache res
+  where ka = kindOf (Proxy @a)
+        kb = kindOf (Proxy @b)
+
+        res st = do mav <- sbvToSV st ma
+
+                    let justVal = SBV $ SVal ka $ Right $ cache $ \_ -> newExpr st ka $ SBVApp MaybeAccess [mav]
+
+                        justRes = brJust justVal
+
+                    br1 <- sbvToSV st brNothing
+                    br2 <- sbvToSV st justRes
+
+                    -- Do we have a value?
+                    noVal <- newExpr st KBool $ SBVApp (MaybeIs ka False) [mav]
+                    newExpr st kb $ SBVApp Ite [noVal, br1, br2]
diff --git a/Data/SBV/Provers/ABC.hs b/Data/SBV/Provers/ABC.hs
--- a/Data/SBV/Provers/ABC.hs
+++ b/Data/SBV/Provers/ABC.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Provers.ABC
--- Author    : Adam Foltzer
+-- Copyright : (c) Adam Foltzer
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -33,10 +33,14 @@
                               , supportsReals              = False
                               , supportsApproxReals        = False
                               , supportsIEEE754            = False
+                              , supportsSets               = False
                               , supportsOptimization       = False
                               , supportsPseudoBooleans     = False
                               , supportsCustomQueries      = False
                               , supportsGlobalDecls        = False
-                              , supportsFlattenedSequences = Nothing
+                              , supportsDataTypes          = False
+                              , supportsDTConstructorSigs  = False
+                              , supportsDTAccessorSigs     = False
+                              , supportsFlattenedModels    = Nothing
                               }
          }
diff --git a/Data/SBV/Provers/Boolector.hs b/Data/SBV/Provers/Boolector.hs
--- a/Data/SBV/Provers/Boolector.hs
+++ b/Data/SBV/Provers/Boolector.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Provers.Boolector
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -31,10 +31,14 @@
                               , supportsReals              = False
                               , supportsApproxReals        = False
                               , supportsIEEE754            = False
+                              , supportsSets               = False
                               , supportsOptimization       = False
                               , supportsPseudoBooleans     = False
                               , supportsCustomQueries      = True
                               , supportsGlobalDecls        = False
-                              , supportsFlattenedSequences = Nothing
+                              , supportsDataTypes          = False
+                              , supportsDTConstructorSigs  = False
+                              , supportsDTAccessorSigs     = False
+                              , supportsFlattenedModels    = Nothing
                               }
          }
diff --git a/Data/SBV/Provers/CVC4.hs b/Data/SBV/Provers/CVC4.hs
--- a/Data/SBV/Provers/CVC4.hs
+++ b/Data/SBV/Provers/CVC4.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Provers.CVC4
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -35,11 +35,15 @@
                               , supportsReals              = True  -- Not quite the same capability as Z3; but works more or less..
                               , supportsApproxReals        = False
                               , supportsIEEE754            = False
+                              , supportsSets               = False
                               , supportsOptimization       = False
                               , supportsPseudoBooleans     = False
                               , supportsCustomQueries      = True
                               , supportsGlobalDecls        = True
-                              , supportsFlattenedSequences = Nothing
+                              , supportsDataTypes          = True
+                              , supportsDTConstructorSigs  = True
+                              , supportsDTAccessorSigs     = False
+                              , supportsFlattenedModels    = Nothing
                               }
          }
   where -- CVC4 wants all input on one line
diff --git a/Data/SBV/Provers/MathSAT.hs b/Data/SBV/Provers/MathSAT.hs
--- a/Data/SBV/Provers/MathSAT.hs
+++ b/Data/SBV/Provers/MathSAT.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Provers.MathSAT
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -35,11 +35,15 @@
                               , supportsReals              = True
                               , supportsApproxReals        = False
                               , supportsIEEE754            = True
+                              , supportsSets               = False
                               , supportsOptimization       = False
                               , supportsPseudoBooleans     = False
                               , supportsCustomQueries      = True
                               , supportsGlobalDecls        = False
-                              , supportsFlattenedSequences = Nothing
+                              , supportsDataTypes          = True
+                              , supportsDTConstructorSigs  = False
+                              , supportsDTAccessorSigs     = False
+                              , supportsFlattenedModels    = Nothing
                               }
          }
 
diff --git a/Data/SBV/Provers/Prover.hs b/Data/SBV/Provers/Prover.hs
--- a/Data/SBV/Provers/Prover.hs
+++ b/Data/SBV/Provers/Prover.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Provers.Prover
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -16,7 +16,6 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns        #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
-{-# LANGUAGE TypeSynonymInstances  #-}
 
 module Data.SBV.Provers.Prover (
          SMTSolver(..), SMTConfig(..), Predicate
@@ -46,7 +45,7 @@
 import Data.Time (getZonedTime, NominalDiffTime, UTCTime, getCurrentTime, diffUTCTime)
 import Data.List (intercalate, isPrefixOf, nub)
 
-import Data.Maybe (mapMaybe)
+import Data.Maybe (mapMaybe, listToMaybe)
 
 import qualified Data.Map.Strict as M
 import qualified Data.Foldable   as S (toList)
@@ -54,9 +53,9 @@
 import Data.SBV.Core.Data
 import Data.SBV.Core.Symbolic
 import Data.SBV.SMT.SMT
+import Data.SBV.SMT.Utils (debug, alignPlain)
 import Data.SBV.Utils.ExtractIO
 import Data.SBV.Utils.TDiff
-import Data.SBV.Utils.PrettyNum
 
 import qualified Data.SBV.Trans.Control as Control
 import qualified Data.SBV.Control.Query as Control
@@ -72,20 +71,24 @@
 import qualified Data.SBV.Provers.ABC        as ABC
 
 mkConfig :: SMTSolver -> SMTLibVersion -> [Control.SMTOption] -> SMTConfig
-mkConfig s smtVersion startOpts = SMTConfig { verbose             = False
-                                            , timing              = NoTiming
-                                            , printBase           = 10
-                                            , printRealPrec       = 16
-                                            , transcript          = Nothing
-                                            , solver              = s
-                                            , smtLibVersion       = smtVersion
-                                            , satCmd              = "(check-sat)"
-                                            , allSatMaxModelCount = Nothing                -- i.e., return all satisfying models
-                                            , isNonModelVar       = const False            -- i.e., everything is a model-variable by default
-                                            , roundingMode        = RoundNearestTiesToEven
-                                            , solverSetOptions    = startOpts
-                                            , ignoreExitCode      = False
-                                            , redirectVerbose     = Nothing
+mkConfig s smtVersion startOpts = SMTConfig { verbose                = False
+                                            , timing                 = NoTiming
+                                            , printBase              = 10
+                                            , printRealPrec          = 16
+                                            , transcript             = Nothing
+                                            , solver                 = s
+                                            , smtLibVersion          = smtVersion
+                                            , satCmd                 = "(check-sat)"
+                                            , satTrackUFs            = True                   -- i.e., yes, do extract UI function values
+                                            , allSatMaxModelCount    = Nothing                -- i.e., return all satisfying models
+                                            , allSatPrintAlong       = False                  -- i.e., do not print models as they are found
+                                            , isNonModelVar          = const False            -- i.e., everything is a model-variable by default
+                                            , validateModel          = False
+                                            , allowQuantifiedQueries = False
+                                            , roundingMode           = RoundNearestTiesToEven
+                                            , solverSetOptions       = startOpts
+                                            , ignoreExitCode         = False
+                                            , redirectVerbose        = Nothing
                                             }
 
 -- | If supported, this makes all output go to stdout, which works better with SBV
@@ -158,7 +161,10 @@
 
   -- | Generalization of 'Data.SBV.proveWith'
   proveWith :: SMTConfig -> a -> m ThmResult
-  proveWith = runWithQuery False $ checkNoOptimizations >> ThmResult <$> Control.getSMTResult
+  proveWith cfg a = do r <- runWithQuery False (checkNoOptimizations >> Control.getSMTResult) cfg a
+                       ThmResult <$> if validateModel cfg
+                                     then validate False cfg a r
+                                     else return r
 
   -- | Generalization of 'Data.SBV.sat'
   sat :: a -> m SatResult
@@ -166,7 +172,10 @@
 
   -- | Generalization of 'Data.SBV.satWith'
   satWith :: SMTConfig -> a -> m SatResult
-  satWith = runWithQuery True $ checkNoOptimizations >> SatResult <$> Control.getSMTResult
+  satWith cfg a = do r <- runWithQuery True (checkNoOptimizations >> Control.getSMTResult) cfg a
+                     SatResult <$> if validateModel cfg
+                                   then validate True cfg a r
+                                   else return r
 
   -- | Generalization of 'Data.SBV.allSat'
   allSat :: a -> m AllSatResult
@@ -174,7 +183,11 @@
 
   -- | Generalization of 'Data.SBV.allSatWith'
   allSatWith :: SMTConfig -> a -> m AllSatResult
-  allSatWith = runWithQuery True $ checkNoOptimizations >> AllSatResult <$> Control.getAllSatResult
+  allSatWith cfg a = do f@(mm, pe, un, rs) <- runWithQuery True (checkNoOptimizations >> Control.getAllSatResult) cfg a
+                        AllSatResult <$> if validateModel cfg
+                                         then do rs' <- mapM (validate True cfg a) rs
+                                                 return (mm, pe, un, rs')
+                                         else return f
 
   -- | Generalization of 'Data.SBV.optimize'
   optimize :: OptimizeStyle -> a -> m OptimizeResult
@@ -187,6 +200,12 @@
                    qinps      <- Control.getQuantifiedInputs
                    spgm       <- Control.getSBVPgm
 
+                   when (validateModel config) $
+                          error $ unlines [ ""
+                                          , "*** Data.SBV: Model validation is not supported in optimization calls."
+                                          , "*** To turn validation off, use `cfg{validateModel = False}`"
+                                          ]
+
                    when (null objectives) $
                           error $ unlines [ ""
                                           , "*** Data.SBV: Unsupported call to optimize when no objectives are present."
@@ -245,9 +264,10 @@
 
                    let optimizerDirectives = concatMap minmax objectives ++ priority style
                          where mkEq (x, y) = "(assert (= " ++ show x ++ " " ++ show y ++ "))"
-                               minmax (Minimize          _  xy@(_, v))     = [mkEq xy, "(minimize "    ++ signAdjust v (show v) ++ ")"]
-                               minmax (Maximize          _  xy@(_, v))     = [mkEq xy, "(maximize "    ++ signAdjust v (show v) ++ ")"]
-                               minmax (AssertWithPenalty nm xy@(_, v) mbp) = [mkEq xy, "(assert-soft " ++ signAdjust v (show v) ++ penalize mbp ++ ")"]
+
+                               minmax (Minimize          _  xy@(_, v))     = [mkEq xy, "(minimize "    ++ show v                 ++ ")"]
+                               minmax (Maximize          _  xy@(_, v))     = [mkEq xy, "(maximize "    ++ show v                 ++ ")"]
+                               minmax (AssertWithPenalty nm xy@(_, v) mbp) = [mkEq xy, "(assert-soft " ++ show v ++ penalize mbp ++ ")"]
                                  where penalize DefaultPenalty    = ""
                                        penalize (Penalty w mbGrp)
                                           | w <= 0         = error $ unlines [ "SBV.AssertWithPenalty: Goal " ++ show nm ++ " is assigned a non-positive penalty: " ++ shw
@@ -262,21 +282,6 @@
                                priority Independent   = ["(set-option :opt.priority box)"]
                                priority (Pareto _)    = ["(set-option :opt.priority pareto)"]
 
-                               -- if the goal is a signed-BV, then we need to add 2^{n-1} to the maximal value
-                               -- is properly placed in the correct range. See http://github.com/Z3Prover/z3/issues/1339 for
-                               -- details on why we have to do this:
-                               signAdjust :: SV -> String -> String
-                               signAdjust v o = case kindOf v of
-                                                  -- NB. The order we spit out the addition here (i.e., "bvadd v constant")
-                                                  -- is important as we parse it back in precisely that form when we
-                                                  -- get the objective. Don't change it!
-                                                  KBounded True sz -> "(bvadd " ++ o ++ " " ++ adjust sz ++ ")"
-                                                  _                -> o
-                                  where adjust :: Int -> String
-                                        adjust sz = cvToSMTLib RoundNearestTiesToEven -- rounding mode doesn't matter here, just pick one
-                                                              (mkConstCV (KBounded False sz)
-                                                                         ((2::Integer)^(fromIntegral sz - (1::Integer))))
-
                    mapM_ (Control.send True) optimizerDirectives
 
                    case style of
@@ -291,7 +296,7 @@
   -- | Generalization of 'Data.SBV.isVacuousWith'
   isVacuousWith :: SMTConfig -> a -> m Bool
   isVacuousWith cfg a = -- NB. Can't call runWithQuery since last constraint would become the implication!
-       fst <$> runSymbolic (SMTMode ISetup True cfg) (forSome_ a >> Control.query check)
+       fst <$> runSymbolic (SMTMode QueryInternal ISetup True cfg) (forSome_ a >> Control.executeQuery QueryInternal check)
      where
        check :: QueryT m Bool
        check = do cs <- Control.checkSat
@@ -325,6 +330,143 @@
                                  SatResult Unsatisfiable{} -> return False
                                  _                         -> error $ "SBV.isSatisfiable: Received: " ++ show r
 
+  -- | Validate a model obtained from the solver
+  validate :: Bool -> SMTConfig -> a -> SMTResult -> m SMTResult
+  validate isSAT cfg p res = case res of
+                               Unsatisfiable{} -> return res
+                               Satisfiable _ m -> case modelBindings m of
+                                                    Nothing  -> error "Data.SBV.validate: Impossible happaned; no bindings during model validation."
+                                                    Just env -> check env
+                               SatExtField{}   -> return $ ProofError cfg [ "Cannot validate models produced during optimization."
+                                                                          , ""
+                                                                          , "To turn validation off, use `cfg{validateModel = False}`"
+                                                                          , ""
+                                                                          , "Unable to validate the produced model."
+                                                                          ]
+                                                                          (Just res)
+                               Unknown{}       -> return res
+                               ProofError{}    -> return res
+
+    where check env = do let envShown = showModelDictionary True True cfg modelBinds
+                                where modelBinds = [(n, fake q s v) | ((q, (s, n)), v) <- env]
+                                      fake q s Nothing
+                                        | q == ALL
+                                        = RegularCV $ CV (kindOf s) $ CUserSort (Nothing, "<universally quantified>")
+                                        | True
+                                        = RegularCV $ CV (kindOf s) $ CUserSort (Nothing, "<no binding found>")
+                                      fake _ _ (Just v) = RegularCV v
+
+                             notify s
+                               | not (verbose cfg) = return ()
+                               | True              = debug cfg ["[VALIDATE] " `alignPlain` s]
+
+                         notify $ "Validating the model in the " ++ if null env then "empty environment." else "environment:"
+                         mapM_ notify ["    " ++ l | l <- lines envShown]
+
+                         result <- snd <$> runSymbolic (Concrete (Just (isSAT, env))) ((if isSAT then forSome_ p else forAll_ p) >>= output)
+
+                         let explain  = [ ""
+                                        , "Environment:"  ++ if null env then " <empty>" else ""
+                                        ]
+                                     ++ [ ""          | not (null env)]
+                                     ++ [ "    " ++ l | l <- lines envShown]
+                                     ++ [ "" ]
+
+                             wrap tag extras = return $ ProofError cfg (tag : explain ++ extras) (Just res)
+
+                             giveUp   s     = wrap ("Data.SBV: Cannot validate the model: " ++ s)
+                                                   [ "SBV's model validator is incomplete, and cannot handle this particular case."
+                                                   , "Please report this as a feature request or possibly a bug!"
+                                                   ]
+
+                             badModel s     = wrap ("Data.SBV: Model validation failure: " ++ s)
+                                                   [ "Backend solver returned a model that does not satisfy the constraints."
+                                                   , "This could indicate a bug in the backend solver, or SBV itself. Please report."
+                                                   ]
+
+                             notConcrete sv = wrap ("Data.SBV: Cannot validate the model, since " ++ show sv ++ " is not concretely computable.")
+                                                   (  perhaps (why sv)
+                                                   ++ [ "SBV's model validator is incomplete, and cannot handle this particular case."
+                                                      , "Please report this as a feature request or possibly a bug!"
+                                                      ]
+                                                   )
+                                  where perhaps Nothing  = []
+                                        perhaps (Just x) = [x, ""]
+
+                                        -- This is incomplete, but should capture the most common cases
+                                        why s = case s `lookup` S.toList (pgmAssignments (resAsgns result)) of
+                                                  Nothing            -> Nothing
+                                                  Just (SBVApp o as) -> case o of
+                                                                          Uninterpreted v   -> Just $ "The value depends on the uninterpreted constant " ++ show v ++ "."
+                                                                          IEEEFP FP_FMA     -> Just "Floating point FMA operation is not supported concretely."
+                                                                          IEEEFP _          -> Just "Not all floating point operations are supported concretely."
+                                                                          OverflowOp _      -> Just "Overflow-checking is not done concretely."
+                                                                          StrOp (StrInRe _) -> Just "Regular expression matches are not supported in validation mode."
+                                                                          _                 -> listToMaybe $ mapMaybe why as
+
+                             cstrs = S.toList $ resConstraints result
+
+                             walkConstraints [] cont = do
+                                unless (null cstrs) $ notify "Validated all constraints."
+                                cont
+                             walkConstraints ((isSoft, attrs, sv) : rest) cont
+                                | kindOf sv /= KBool
+                                = giveUp $ "Constraint tied to " ++ show sv ++ " is non-boolean."
+                                | isSoft || sv == trueSV
+                                = walkConstraints rest cont
+                                | sv == falseSV
+                                = case mbName of
+                                    Just nm -> badModel $ "Named constraint " ++ show nm ++ " evaluated to False."
+                                    Nothing -> badModel "A constraint was violated."
+                                | True
+                                = notConcrete sv
+                                where mbName = listToMaybe [n | (":named", n) <- attrs]
+
+                             -- SAT: All outputs must be true
+                             satLoop []
+                               = do notify "All outputs are satisfied. Validation complete."
+                                    return res
+                             satLoop (sv:svs)
+                               | kindOf sv /= KBool
+                               = giveUp $ "Output tied to " ++ show sv ++ " is non-boolean."
+                               | sv == trueSV
+                               = satLoop svs
+                               | sv == falseSV
+                               = badModel "Final output evaluated to False."
+                               | True
+                               = notConcrete sv
+
+                             -- Proof: At least one output must be false
+                             proveLoop [] somethingFailed
+                               | somethingFailed = do notify "Counterexample is validated."
+                                                      return res
+                               | True            = do notify "Counterexample violates none of the outputs."
+                                                      badModel "Counter-example violates no constraints."
+                             proveLoop (sv:svs) somethingFailed
+                               | kindOf sv /= KBool
+                               = giveUp $ "Output tied to " ++ show sv ++ " is non-boolean."
+                               | sv == trueSV
+                               = proveLoop svs somethingFailed
+                               | sv == falseSV
+                               = proveLoop svs True
+                               | True
+                               = notConcrete sv
+
+                             -- Output checking is tricky, since we behave differently for different modes
+                             checkOutputs []
+                               | null cstrs
+                               = giveUp "Impossible happened: There are no outputs nor any constraints to check."
+                             checkOutputs os
+                               = do notify "Validating outputs."
+                                    if isSAT then satLoop   os
+                                             else proveLoop os False
+
+                         notify $ if null cstrs
+                                  then "There are no constraints to check."
+                                  else "Validating " ++ show (length cstrs) ++ " constraint(s)."
+
+                         walkConstraints cstrs (checkOutputs (resOutputs result))
+
 -- | `Provable` is specialization of `MProvable` to the `IO` monad. Unless you are using
 -- transformers explicitly, this is the type you should prefer.
 type Provable = MProvable IO
@@ -364,9 +506,9 @@
       let comments = ["Automatically created by SBV on " ++ show t]
           cfg      = defaultSMTCfg { smtLibVersion = SMTLib2 }
 
-      (_, res) <- runSymbolic (SMTMode ISetup isSat cfg) $ (if isSat then forSome_ else forAll_) a >>= output
+      (_, res) <- runSymbolic (SMTMode QueryInternal ISetup isSat cfg) $ (if isSat then forSome_ else forAll_) a >>= output
 
-      let SMTProblem{smtLibPgm} = Control.runProofOn (SMTMode IRun isSat cfg) QueryInternal comments res
+      let SMTProblem{smtLibPgm} = Control.runProofOn (SMTMode QueryInternal IRun isSat cfg) QueryInternal comments res
           out                   = show (smtLibPgm cfg)
 
       return $ out ++ "\n(check-sat)\n"
@@ -499,11 +641,11 @@
 
 -- | Generalization of 'Data.SBV.runSMTWith'
 runSMTWith :: MonadIO m => SMTConfig -> SymbolicT m a -> m a
-runSMTWith cfg a = fst <$> runSymbolic (SMTMode ISetup True cfg) a
+runSMTWith cfg a = fst <$> runSymbolic (SMTMode QueryExternal ISetup True cfg) a
 
 -- | Runs with a query.
 runWithQuery :: MProvable m a => Bool -> QueryT m b -> SMTConfig -> a -> m b
-runWithQuery isSAT q cfg a = fst <$> runSymbolic (SMTMode ISetup isSAT cfg) comp
+runWithQuery isSAT q cfg a = fst <$> runSymbolic (SMTMode QueryInternal ISetup isSAT cfg) comp
   where comp =  do _ <- (if isSAT then forSome_ else forAll_) a >>= output
                    Control.executeQuery QueryInternal q
 
@@ -566,9 +708,9 @@
                        let mkRelative path
                               | cwd `isPrefixOf` path = drop (length cwd) path
                               | True                  = path
-                       fst <$> runSymbolic (SMTMode ISafe True cfg) (sName_ a >> check mkRelative)
+                       fst <$> runSymbolic (SMTMode QueryInternal ISafe True cfg) (sName_ a >> check mkRelative)
      where check :: (FilePath -> FilePath) -> SymbolicT m [SafeResult]
-           check mkRelative = Control.query $ Control.getSBVAssertions >>= mapM (verify mkRelative)
+           check mkRelative = Control.executeQuery QueryInternal $ Control.getSBVAssertions >>= mapM (verify mkRelative)
 
            -- check that the cond is unsatisfiable. If satisfiable, that would
            -- indicate the assignment under which the 'Data.SBV.sAssert' would fail
diff --git a/Data/SBV/Provers/Yices.hs b/Data/SBV/Provers/Yices.hs
--- a/Data/SBV/Provers/Yices.hs
+++ b/Data/SBV/Provers/Yices.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Provers.Yices
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -33,10 +33,14 @@
                               , supportsReals              = True
                               , supportsApproxReals        = False
                               , supportsIEEE754            = False
+                              , supportsSets               = False
                               , supportsOptimization       = False
                               , supportsPseudoBooleans     = False
                               , supportsCustomQueries      = True
                               , supportsGlobalDecls        = False
-                              , supportsFlattenedSequences = Nothing
+                              , supportsDataTypes          = False
+                              , supportsDTConstructorSigs  = False
+                              , supportsDTAccessorSigs     = False
+                              , supportsFlattenedModels    = Nothing
                               }
          }
diff --git a/Data/SBV/Provers/Z3.hs b/Data/SBV/Provers/Z3.hs
--- a/Data/SBV/Provers/Z3.hs
+++ b/Data/SBV/Provers/Z3.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Provers.Z3
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -33,11 +33,15 @@
                               , supportsReals              = True
                               , supportsApproxReals        = True
                               , supportsIEEE754            = True
+                              , supportsSets               = True
                               , supportsOptimization       = True
                               , supportsPseudoBooleans     = True
                               , supportsCustomQueries      = True
                               , supportsGlobalDecls        = True
-                              , supportsFlattenedSequences = Just [ "(set-option :pp.max_depth      4294967295)"
+                              , supportsDataTypes          = True
+                              , supportsDTConstructorSigs  = False
+                              , supportsDTAccessorSigs     = True
+                              , supportsFlattenedModels    = Just [ "(set-option :pp.max_depth      4294967295)"
                                                                   , "(set-option :pp.min_alias_size 4294967295)"
                                                                   ]
                               }
diff --git a/Data/SBV/RegExp.hs b/Data/SBV/RegExp.hs
--- a/Data/SBV/RegExp.hs
+++ b/Data/SBV/RegExp.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.RegExp
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -14,12 +14,11 @@
 -- this module.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE OverloadedStrings    #-}
-{-# LANGUAGE Rank2Types           #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeApplications     #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
 
 module Data.SBV.RegExp (
         -- * Regular expressions
diff --git a/Data/SBV/SMT/SMT.hs b/Data/SBV/SMT/SMT.hs
--- a/Data/SBV/SMT/SMT.hs
+++ b/Data/SBV/SMT/SMT.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.SMT.SMT
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -21,7 +21,7 @@
        , SatModel(..), genParse
        , extractModels, getModelValues
        , getModelDictionaries, getModelUninterpretedValues
-       , displayModels, showModel
+       , displayModels, showModel, shCV, showModelDictionary
 
        -- * Standard prover engine
        , standardEngine
@@ -43,7 +43,7 @@
 import Data.Char          (isSpace)
 import Data.Maybe         (fromMaybe, isJust)
 import Data.Int           (Int8, Int16, Int32, Int64)
-import Data.List          (intercalate, isPrefixOf)
+import Data.List          (intercalate, isPrefixOf, transpose)
 import Data.Word          (Word8, Word16, Word32, Word64)
 
 import Data.IORef (readIORef, writeIORef)
@@ -61,6 +61,8 @@
 import Data.SBV.Core.AlgReals
 import Data.SBV.Core.Data
 import Data.SBV.Core.Symbolic (SMTEngine, State(..))
+import Data.SBV.Core.Concrete (showCV)
+import Data.SBV.Core.Kind     (showBaseKind)
 
 import Data.SBV.SMT.Utils     (showTimeoutValue, alignPlain, debug, mergeSExpr, SBVException(..))
 
@@ -73,11 +75,11 @@
 
 -- | Extract the final configuration from a result
 resultConfig :: SMTResult -> SMTConfig
-resultConfig (Unsatisfiable c _) = c
-resultConfig (Satisfiable   c _) = c
-resultConfig (SatExtField   c _) = c
-resultConfig (Unknown       c _) = c
-resultConfig (ProofError    c _) = c
+resultConfig (Unsatisfiable c _  ) = c
+resultConfig (Satisfiable   c _  ) = c
+resultConfig (SatExtField   c _  ) = c
+resultConfig (Unknown       c _  ) = c
+resultConfig (ProofError    c _ _) = c
 
 -- | A 'Data.SBV.prove' call results in a 'ThmResult'
 newtype ThmResult = ThmResult SMTResult
@@ -90,8 +92,9 @@
 
 -- | An 'Data.SBV.allSat' call results in a 'AllSatResult'. The first boolean says whether we
 -- hit the max-model limit as we searched. The second boolean says whether
--- there were prefix-existentials.
-newtype AllSatResult = AllSatResult (Bool, Bool, [SMTResult])
+-- there were prefix-existentials. The third boolean says whether we stopped because
+-- the solver returned 'Unknown'.
+newtype AllSatResult = AllSatResult (Bool, Bool, Bool, [SMTResult])
 
 -- | A 'Data.SBV.safe' call results in a 'SafeResult'
 newtype SafeResult   = SafeResult   (Maybe String, String, SMTResult)
@@ -126,17 +129,22 @@
 -- The Show instance of AllSatResults. Note that we have to be careful in being lazy enough
 -- as the typical use case is to pull results out as they become available.
 instance Show AllSatResult where
-  show (AllSatResult (l, e, xs)) = go (0::Int) xs
-    where uniqueWarn | e    = " (Unique up to prefix existentials.)"
-                     | True = ""
+  show (AllSatResult (l, e, u, xs)) = go (0::Int) xs
+    where warnings = case (e, u) of
+                       (False, False) -> ""
+                       (False, True)  -> " (Search stopped since solver has returned unknown.)"
+                       (True,  False) -> " (Unique up to prefix existentials.)"
+                       (True,  True)  -> " (Search stopped becase solver has returned unknown, only prefix existentials were considered.)"
+
           go c (s:ss) = let c'      = c+1
                             (ok, o) = sh c' s
                         in c' `seq` if ok then o ++ "\n" ++ go c' ss else o
           go c []     = case (l, c) of
-                          (True,  _) -> "Search stopped since model count request was reached." ++ uniqueWarn
+                          (True,  _) -> "Search stopped since model count request was reached." ++ warnings
                           (False, 0) -> "No solutions found."
-                          (False, 1) -> "This is the only solution." ++ uniqueWarn
-                          (False, _) -> "Found " ++ show c ++ " different solutions." ++ uniqueWarn
+                          (False, 1) -> "This is the only solution." ++ warnings
+                          (False, _) -> "Found " ++ show c ++ " different solutions." ++ warnings
+
           sh i c = (ok, showSMTResult "Unsatisfiable"
                                       "Unknown"
                                       ("Solution #" ++ show i ++ ":\nSatisfiable") ("Solution #" ++ show i ++ ":\n")
@@ -153,7 +161,7 @@
 
                IndependentResult   rs  -> multi "objectives" (map (uncurry shI) rs)
 
-               ParetoResult (False, [r]) -> sh (\s -> "Unique pareto front: " ++ s) r
+               ParetoResult (False, [r]) -> sh ("Unique pareto front: " ++) r
                ParetoResult (False, rs)  -> multi "pareto optimal values" (zipWith shP [(1::Int)..] rs)
                ParetoResult (True,  rs)  ->    multi "pareto optimal values" (zipWith shP [(1::Int)..] rs)
                                            ++ "\n*** Note: Pareto-front extraction was terminated as requested by the user."
@@ -349,44 +357,53 @@
   getModelObjectiveValue :: String -> a -> Maybe GeneralizedCV
   getModelObjectiveValue v r = v `M.lookup` getModelObjectives r
 
+  -- | Extract model uninterpreted-functions
+  getModelUIFuns :: a -> M.Map String (SBVType, ([([CV], CV)], CV))
+
+  -- | Extract the value of an uninterpreted-function as an association list
+  getModelUIFunValue :: String -> a -> Maybe (SBVType, ([([CV], CV)], CV))
+  getModelUIFunValue v r = v `M.lookup` getModelUIFuns r
+
 -- | Return all the models from an 'Data.SBV.allSat' call, similar to 'extractModel' but
 -- is suitable for the case of multiple results.
 extractModels :: SatModel a => AllSatResult -> [a]
-extractModels (AllSatResult (_, _, xs)) = [ms | Right (_, ms) <- map getModelAssignment xs]
+extractModels (AllSatResult (_, _, _, xs)) = [ms | Right (_, ms) <- map getModelAssignment xs]
 
 -- | Get dictionaries from an all-sat call. Similar to `getModelDictionary`.
 getModelDictionaries :: AllSatResult -> [M.Map String CV]
-getModelDictionaries (AllSatResult (_, _, xs)) = map getModelDictionary xs
+getModelDictionaries (AllSatResult (_, _, _, xs)) = map getModelDictionary xs
 
 -- | Extract value of a variable from an all-sat call. Similar to `getModelValue`.
 getModelValues :: SymVal b => String -> AllSatResult -> [Maybe b]
-getModelValues s (AllSatResult (_, _, xs)) =  map (s `getModelValue`) xs
+getModelValues s (AllSatResult (_, _, _, xs)) =  map (s `getModelValue`) xs
 
 -- | Extract value of an uninterpreted variable from an all-sat call. Similar to `getModelUninterpretedValue`.
 getModelUninterpretedValues :: String -> AllSatResult -> [Maybe String]
-getModelUninterpretedValues s (AllSatResult (_, _, xs)) =  map (s `getModelUninterpretedValue`) xs
+getModelUninterpretedValues s (AllSatResult (_, _, _, xs)) =  map (s `getModelUninterpretedValue`) xs
 
 -- | 'ThmResult' as a generic model provider
 instance Modelable ThmResult where
   getModelAssignment (ThmResult r) = getModelAssignment r
-  modelExists        (ThmResult r) = modelExists r
+  modelExists        (ThmResult r) = modelExists        r
   getModelDictionary (ThmResult r) = getModelDictionary r
   getModelObjectives (ThmResult r) = getModelObjectives r
+  getModelUIFuns     (ThmResult r) = getModelUIFuns     r
 
 -- | 'SatResult' as a generic model provider
 instance Modelable SatResult where
   getModelAssignment (SatResult r) = getModelAssignment r
-  modelExists        (SatResult r) = modelExists r
+  modelExists        (SatResult r) = modelExists        r
   getModelDictionary (SatResult r) = getModelDictionary r
   getModelObjectives (SatResult r) = getModelObjectives r
+  getModelUIFuns     (SatResult r) = getModelUIFuns     r
 
 -- | 'SMTResult' as a generic model provider
 instance Modelable SMTResult where
-  getModelAssignment (Unsatisfiable _ _) = Left "SBV.getModelAssignment: Unsatisfiable result"
-  getModelAssignment (Satisfiable _ m)   = Right (False, parseModelOut m)
-  getModelAssignment (SatExtField _ _)   = Left "SBV.getModelAssignment: The model is in an extension field"
-  getModelAssignment (Unknown _ m)       = Left $ "SBV.getModelAssignment: Solver state is unknown: " ++ show m
-  getModelAssignment (ProofError _ s)    = error $ unlines $ "Backend solver complains: " : s
+  getModelAssignment (Unsatisfiable _ _  ) = Left "SBV.getModelAssignment: Unsatisfiable result"
+  getModelAssignment (Satisfiable   _ m  ) = Right (False, parseModelOut m)
+  getModelAssignment (SatExtField   _ _  ) = Left "SBV.getModelAssignment: The model is in an extension field"
+  getModelAssignment (Unknown       _ m  ) = Left $ "SBV.getModelAssignment: Solver state is unknown: " ++ show m
+  getModelAssignment (ProofError    _ s _) = error $ unlines $ "SBV.getModelAssignment: Failed to produce a model: " : s
 
   modelExists Satisfiable{}   = True
   modelExists Unknown{}       = False -- don't risk it
@@ -404,6 +421,12 @@
   getModelObjectives Unknown{}         = M.empty
   getModelObjectives ProofError{}      = M.empty
 
+  getModelUIFuns Unsatisfiable{}   = M.empty
+  getModelUIFuns (Satisfiable _ m) = M.fromList (modelUIFuns m)
+  getModelUIFuns (SatExtField _ m) = M.fromList (modelUIFuns m)
+  getModelUIFuns Unknown{}         = M.empty
+  getModelUIFuns ProofError{}      = M.empty
+
 -- | Extract a model out, will throw error if parsing is unsuccessful
 parseModelOut :: SatModel a => SMTModel -> a
 parseModelOut m = case parseCVs [c | (_, c) <- modelAssocs m] of
@@ -416,7 +439,7 @@
 -- 'Int' argument to @disp@ 'is the current model number. The second argument is a tuple, where the first
 -- element indicates whether the model is alleged (i.e., if the solver is not sure, returing Unknown)
 displayModels :: SatModel a => (Int -> (Bool, a) -> IO ()) -> AllSatResult -> IO Int
-displayModels disp (AllSatResult (_, _, ms)) = do
+displayModels disp (AllSatResult (_, _, _, ms)) = do
     inds <- zipWithM display [a | Right a <- map (getModelAssignment . SatResult) ms] [(1::Int)..]
     return $ last (0:inds)
   where display r i = disp i r >> return i
@@ -424,13 +447,20 @@
 -- | Show an SMTResult; generic version
 showSMTResult :: String -> String -> String -> String -> String -> SMTResult -> String
 showSMTResult unsatMsg unkMsg satMsg satMsgModel satExtMsg result = case result of
-  Unsatisfiable _ uc            -> unsatMsg ++ showUnsatCore uc
-  Satisfiable _ (SMTModel _ []) -> satMsg
-  Satisfiable _ m               -> satMsgModel ++ showModel cfg m
-  SatExtField _ (SMTModel b _)  -> satExtMsg   ++ showModelDictionary cfg b
-  Unknown     _ r               -> unkMsg ++ ".\n" ++ "  Reason: " `alignPlain` show r
-  ProofError  _ []              -> "*** An error occurred. No additional information available. Try running in verbose mode"
-  ProofError  _ ls              -> "*** An error occurred.\n" ++ intercalate "\n" (map ("***  " ++) ls)
+  Unsatisfiable _ uc                 -> unsatMsg ++ showUnsatCore uc
+  Satisfiable _ (SMTModel _ _ [] []) -> satMsg
+  Satisfiable _ m                    -> satMsgModel ++ showModel cfg m
+  SatExtField _ (SMTModel b _ _ _)   -> satExtMsg   ++ showModelDictionary True False cfg b
+  Unknown     _ r                    -> unkMsg ++ ".\n" ++ "  Reason: " `alignPlain` show r
+  ProofError  _ [] Nothing           -> "*** An error occurred. No additional information available. Try running in verbose mode."
+  ProofError  _ ls Nothing           -> "*** An error occurred.\n" ++ intercalate "\n" (map ("***  " ++) ls)
+  ProofError  _ ls (Just r)          -> intercalate "\n" $  [ "*** " ++ l | l <- ls]
+                                                         ++ [ "***"
+                                                            , "*** Alleged model:"
+                                                            , "***"
+                                                            ]
+                                                         ++ ["*** "  ++ l | l <- lines (showSMTResult unsatMsg unkMsg satMsg satMsgModel satExtMsg r)]
+
  where cfg = resultConfig result
        showUnsatCore Nothing   = ""
        showUnsatCore (Just xs) = ". Unsat core:\n" ++ intercalate "\n" ["    " ++ x | x <- xs]
@@ -438,20 +468,32 @@
 -- | Show a model in human readable form. Ignore bindings to those variables that start
 -- with "__internal_sbv_" and also those marked as "nonModelVar" in the config; as these are only for internal purposes
 showModel :: SMTConfig -> SMTModel -> String
-showModel cfg model = showModelDictionary cfg [(n, RegularCV c) | (n, c) <- modelAssocs model]
+showModel cfg model
+   | null uiFuncs
+   = nonUIFuncs
+   | True
+   = sep nonUIFuncs ++ intercalate "\n\n" (map (showModelUI cfg) uiFuncs)
+   where nonUIFuncs = showModelDictionary (null uiFuncs) False cfg [(n, RegularCV c) | (n, c) <- modelAssocs model]
+         uiFuncs    = modelUIFuns model
+         sep ""     = ""
+         sep x      = x ++ "\n\n"
 
 -- | Show bindings in a generalized model dictionary, tabulated
-showModelDictionary :: SMTConfig -> [(String, GeneralizedCV)] -> String
-showModelDictionary cfg allVars
+showModelDictionary :: Bool -> Bool -> SMTConfig -> [(String, GeneralizedCV)] -> String
+showModelDictionary warnEmpty includeEverything cfg allVars
    | null allVars
-   = "[There are no variables bound by the model.]"
+   = warn "[There are no variables bound by the model.]"
    | null relevantVars
-   = "[There are no model-variables bound by the model.]"
+   = warn "[There are no model-variables bound by the model.]"
    | True
    = intercalate "\n" . display . map shM $ relevantVars
-  where relevantVars  = filter (not . ignore) allVars
-        ignore (s, _) = "__internal_sbv_" `isPrefixOf` s || isNonModelVar cfg s
+  where warn s = if warnEmpty then s else ""
 
+        relevantVars  = filter (not . ignore) allVars
+        ignore (s, _)
+          | includeEverything = False
+          | True              = "__internal_sbv_" `isPrefixOf` s || isNonModelVar cfg s
+
         shM (s, RegularCV v) = let vs = shCV cfg v in ((length s, s), (vlength vs, vs))
         shM (s, other)       = let vs = show other in ((length s, s), (vlength vs, vs))
 
@@ -472,6 +514,45 @@
 
         lTrimRight = length . dropWhile isSpace . reverse
 
+-- | Show an uninterpreted function
+showModelUI :: SMTConfig -> (String, (SBVType, ([([CV], CV)], CV))) -> String
+showModelUI cfg (nm, (SBVType ts, (defs, dflt))) = intercalate "\n" ["  " ++ l | l <- sig : map align body]
+  where noOfArgs = length ts - 1
+
+        sig      = nm ++ " :: " ++ intercalate " -> " (map showBaseKind ts)
+
+        ls       = map line defs
+        defLine  = (nm : replicate noOfArgs "_", scv dflt)
+
+        body     = ls ++ [defLine]
+
+        colWidths = [maximum (0 : map length col) | col <- transpose (map fst body)]
+
+        resWidth  = maximum  (0 : map (length . snd) body)
+
+        align (xs, r) = unwords $ zipWith left colWidths xs ++ ["=", left resWidth r]
+           where left i x = take i (x ++ repeat ' ')
+
+        scv = sh (printBase cfg)
+          where sh 2  = binP
+                sh 10 = showCV False
+                sh 16 = hexP
+                sh _  = show
+
+        -- NB. If we have a float NaN/Infinity/+0/-0 etc. these will
+        -- simply print as is, but will not be valid patterns. (We
+        -- have the semi-goal of being able to paste these definitions
+        -- in a Haskell file.) For the time being, punt on this, but
+        -- we might want to do this properly later somehow. (Perhaps
+        -- using some sort of a view pattern.)
+        line :: ([CV], CV) -> ([String], String)
+        line (args, r) = (nm : map (paren . scv) args, scv r)
+          where -- If negative, parenthesize. I think this is the only case
+                -- we need to worry about. Hopefully!
+                paren :: String -> String
+                paren x@('-':_) = '(' : x ++ ")"
+                paren x         = x
+
 -- | Show a constant value, in the user-specified base
 shCV :: SMTConfig -> CV -> String
 shCV = sh . printBase
@@ -587,8 +668,8 @@
                       where safeGetLine isFirst h =
                                          let timeOutToUse | isFirst = mbTimeOut
                                                           | True    = Just 5000000
-                                             timeOutMsg t | isFirst = "User specified timeout of " ++ showTimeoutValue t ++ " exceeded."
-                                                          | True    = "A multiline complete response wasn't received before " ++ showTimeoutValue t ++ " exceeded."
+                                             timeOutMsg t | isFirst = "User specified timeout of " ++ showTimeoutValue t ++ " exceeded"
+                                                          | True    = "A multiline complete response wasn't received before " ++ showTimeoutValue t ++ " exceeded"
 
                                              -- Like hGetLine, except it keeps getting lines if inside a string.
                                              getFullLine :: IO String
@@ -680,6 +761,9 @@
                                 ++ [ "Std-out  : " ++ intercalate "\n           " (lines out) | not (null out)]
                                 ++ [ "Std-err  : " ++ intercalate "\n           " (lines err) | not (null err)]
 
+                           finalizeTranscript (transcript cfg) ex
+                           recordEndTime cfg ctx
+
                            case ex of
                              ExitSuccess -> return ()
                              _           -> if ignoreExitCode cfg
@@ -815,17 +899,14 @@
                              continuation ctx
 
       -- NB. Don't use 'bracket' here, as it wouldn't have access to the exception.
-      let launchSolver = do startTranscript    (transcript cfg) cfg
-                            r <- executeSolver
-                            finalizeTranscript (transcript cfg) Nothing
-                            recordEndTime      cfg ctx
-                            return r
+      let launchSolver = do startTranscript (transcript cfg) cfg
+                            executeSolver
 
       launchSolver `C.catch` (\(e :: C.SomeException) -> handleAsync e $ do terminateProcess pid
                                                                             ec <- waitForProcess pid
                                                                             recordException    (transcript cfg) (show e)
-                                                                            finalizeTranscript (transcript cfg) (Just ec)
-                                                                            recordEndTime      cfg ctx
+                                                                            finalizeTranscript (transcript cfg) ec
+                                                                            recordEndTime cfg ctx
                                                                             C.throwIO e)
 
 -- | Compute and report the end time
@@ -857,19 +938,19 @@
                                   ]
 
 -- | Finish up the transcript file.
-finalizeTranscript :: Maybe FilePath -> Maybe ExitCode -> IO ()
-finalizeTranscript Nothing  _    = return ()
-finalizeTranscript (Just f) mbEC = do ts <- show <$> getZonedTime
-                                      appendFile f $ end ts
-  where end ts = unlines $ [ ""
-                           , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
-                           , ";;;"
-                           , ";;; SBV: Finished at " ++ ts
-                           ]
-                       ++  [ ";;;\n;;; Exit code: " ++ show ec | Just ec <- [mbEC] ]
-                       ++  [ ";;;"
-                           , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
-                           ]
+finalizeTranscript :: Maybe FilePath -> ExitCode -> IO ()
+finalizeTranscript Nothing  _  = return ()
+finalizeTranscript (Just f) ec = do ts <- show <$> getZonedTime
+                                    appendFile f $ end ts
+  where end ts = unlines [ ""
+                         , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
+                         , ";;;"
+                         , ";;; SBV: Finished at " ++ ts
+                         , ";;;"
+                         , ";;; Exit code: " ++ show ec
+                         , ";;;"
+                         , ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"
+                         ]
 
 -- If requested, record in the transcript file
 recordTranscript :: Maybe FilePath -> Either (String, Maybe Int) String -> IO ()
diff --git a/Data/SBV/SMT/SMTLib.hs b/Data/SBV/SMT/SMTLib.hs
--- a/Data/SBV/SMT/SMTLib.hs
+++ b/Data/SBV/SMT/SMTLib.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.SMT.SMTLib
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/SMT/SMTLib2.hs b/Data/SBV/SMT/SMTLib2.hs
--- a/Data/SBV/SMT/SMTLib2.hs
+++ b/Data/SBV/SMT/SMTLib2.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.SMT.SMTLib2
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -15,7 +15,7 @@
 
 import Data.Bits  (bit)
 import Data.List  (intercalate, partition, unzip3, nub, sort)
-import Data.Maybe (listToMaybe, fromMaybe)
+import Data.Maybe (listToMaybe, fromMaybe, catMaybes)
 
 import qualified Data.Foldable as F (toList)
 import qualified Data.Map.Strict      as M
@@ -24,8 +24,8 @@
 import qualified Data.Set             as Set
 
 import Data.SBV.Core.Data
-import Data.SBV.Core.Symbolic (QueryContext(..))
-import Data.SBV.Core.Kind (smtType)
+import Data.SBV.Core.Symbolic (QueryContext(..), SetOp(..))
+import Data.SBV.Core.Kind (smtType, needsFlattening)
 import Data.SBV.SMT.Utils
 import Data.SBV.Control.Types
 
@@ -49,10 +49,24 @@
         hasNonBVArrays = (not . null) [() | (_, (_, (k1, k2), _)) <- arrs, not (isBounded k1 && isBounded k2)]
         hasArrayInits  = (not . null) [() | (_, (_, _, ArrayFree (Just _))) <- arrs]
         hasList        = any isList kindInfo
+        hasSets        = any isSet kindInfo
         hasTuples      = not . null $ tupleArities
+        hasEither      = any isEither kindInfo
+        hasMaybe       = any isMaybe  kindInfo
         rm             = roundingMode cfg
         solverCaps     = capabilities (solver cfg)
 
+        -- Is there a reason why we can't handle this problem?
+        -- NB. There's probably a lot more checking we can do here, but this is a start:
+        doesntHandle = listToMaybe [nope w | (w, have, need) <- checks, need && not have]
+           where checks = [ ("data types",     supportsDataTypes solverCaps, hasTuples || hasEither || hasMaybe)
+                          , ("set operations", supportsSets      solverCaps, hasSets)
+                          ]
+
+                 nope w = [ "***     Given problem requires support for " ++ w
+                          , "***     But the chosen solver (" ++ show (name (solver cfg)) ++ ") doesn't support this feature."
+                          ]
+
         -- Determining the logic is surprisingly tricky!
         logic
            -- user told us what to do: so just take it:
@@ -67,6 +81,17 @@
                Logic_NONE -> ["; NB. Not setting the logic per user request of Logic_NONE"]
                _          -> ["(set-logic " ++ show l ++ ") ; NB. User specified."]
 
+           -- There's a reason why we can't handle this problem:
+           | Just cantDo <- doesntHandle
+           = error $ unlines $   [ ""
+                                 , "*** SBV is unable to choose a proper solver configuration:"
+                                 , "***"
+                                 ]
+                             ++ cantDo
+                             ++ [ "***"
+                                , "*** Please report this as a feature request, either for SBV or the backend solver."
+                                ]
+
            -- Otherwise, we try to determine the most suitable logic.
            -- NB. This isn't really fool proof!
 
@@ -84,12 +109,15 @@
              else if hasBVs
                   then ["(set-logic QF_FPBV)"]
                   else ["(set-logic QF_FP)"]
-           | hasInteger || hasReal || not (null usorts) || hasNonBVArrays || hasTuples
+           | hasInteger || hasReal || not (null usorts) || hasNonBVArrays || hasTuples || hasEither || hasMaybe || hasSets
            = let why | hasInteger        = "has unbounded values"
                      | hasReal           = "has algebraic reals"
                      | not (null usorts) = "has user-defined sorts"
                      | hasNonBVArrays    = "has non-bitvector arrays"
                      | hasTuples         = "has tuples"
+                     | hasEither         = "has either type"
+                     | hasMaybe          = "has maybe type"
+                     | hasSets           = "has sets"
                      | True              = "cannot determine the SMTLib-logic to use"
              in ["(set-logic ALL) ; "  ++ why ++ ", using catch-all."]
 
@@ -109,7 +137,7 @@
 
         -- SBV always requires the production of models!
         getModels   = "(set-option :produce-models true)"
-                    : concat [flattenConfig | hasList, Just flattenConfig <- [supportsFlattenedSequences solverCaps]]
+                    : concat [flattenConfig | any needsFlattening kindInfo, Just flattenConfig <- [supportsFlattenedModels solverCaps]]
 
         -- process all other settings we're given
         userSettings = concatMap opts $ solverSetOptions cfg
@@ -126,6 +154,9 @@
              ++ concatMap declSort usorts
              ++ [ "; --- tuples ---" ]
              ++ concatMap declTuple tupleArities
+             ++ [ "; --- sums ---" ]
+             ++ (if containsSum   kindInfo then declSum   else [])
+             ++ (if containsMaybe kindInfo then declMaybe else [])
              ++ [ "; --- literal constants ---" ]
              ++ concatMap (declConst cfg) consts
              ++ [ "; --- skolem constants ---" ]
@@ -243,7 +274,7 @@
 
            where finals  = cstrs' ++ maybe [] (\r -> [(False, [], r)]) mbO
 
-                 cstrs' =  [(isSoft, attrs, c') | (isSoft, attrs, c) <- cstrs, Just c' <- [pos c]]
+                 cstrs' =  [(isSoft, attrs, c') | (isSoft, attrs, c) <- F.toList cstrs, Just c' <- [pos c]]
 
                  mbO | isSat = pos out
                      | True  = neg out
@@ -281,7 +312,7 @@
   | s == "RoundingMode" -- built-in-sort; so don't declare.
   = []
 declSort (s, Left  r ) = ["(declare-sort " ++ s ++ " 0)  ; N.B. Uninterpreted: " ++ r]
-declSort (s, Right fs) = [ "(declare-datatypes () ((" ++ s ++ " " ++ unwords (map (\c -> "(" ++ c ++ ")") fs) ++ ")))"
+declSort (s, Right fs) = [ "(declare-datatypes ((" ++ s ++ " 0)) ((" ++ unwords (map (\c -> "(" ++ c ++ ")") fs) ++ ")))"
                          , "(define-fun " ++ s ++ "_constrIndex ((x " ++ s ++ ")) Int"
                          ] ++ ["   " ++ body fs (0::Int)] ++ [")"]
         where body []     _ = ""
@@ -299,7 +330,7 @@
 -- @
 declTuple :: Int -> [String]
 declTuple arity
-  | arity == 0 = ["(declare-datatypes () ((SBVTuple0 SBVTuple0)))"]
+  | arity == 0 = ["(declare-datatypes ((SBVTuple0 0)) (((mkSBVTuple0))))"]
   | arity == 1 = error "Data.SBV.declTuple: Unexpected one-tuple"
   | True       =    (l1 ++ "(par (" ++ unwords [param i | i <- [1..arity]] ++ ")")
                  :  [pre i ++ proj i ++ post i    | i <- [1..arity]]
@@ -325,13 +356,42 @@
                     $ Set.map length
                     $ Set.fromList [ tupKs | KTuple tupKs <- Set.toList ks ]
 
--- | Convert in a query context
+-- | Is @Either@ being used?
+containsSum :: Set Kind -> Bool
+containsSum = not . Set.null . Set.filter isEither
+
+-- | Is @Maybe@ being used?
+containsMaybe :: Set Kind -> Bool
+containsMaybe = not . Set.null . Set.filter isMaybe
+
+declSum :: [String]
+declSum = [ "(declare-datatypes ((SBVEither 2)) ((par (T1 T2)"
+          , "                                    ((left_SBVEither  (get_left_SBVEither  T1))"
+          , "                                     (right_SBVEither (get_right_SBVEither T2))))))"
+          ]
+
+declMaybe :: [String]
+declMaybe = [ "(declare-datatypes ((SBVMaybe 1)) ((par (T)"
+            , "                                    ((nothing_SBVMaybe)"
+            , "                                     (just_SBVMaybe (get_just_SBVMaybe T))))))"
+            ]
+
+-- | Convert in a query context.
+-- NB. We do not store everything in @newKs@ below, but only what we need
+-- to do as an extra in the incremental context. See `Data.SBV.Core.Symbolic.registerKind`
+-- for a list of what we include, in case something doesn't show up
+-- and you need it!
 cvtInc :: Bool -> SMTLibIncConverter [String]
-cvtInc afterAPush inps newKs consts arrs tbls uis (SBVPgm asgnsSeq) cfg =
+cvtInc afterAPush inps newKs consts arrs tbls uis (SBVPgm asgnsSeq) cstrs cfg =
+            -- any new settings?
+               settings
             -- sorts
-               concatMap declSort [(s, dt) | KUninterpreted s dt <- Set.toList newKs]
+            ++ concatMap declSort [(s, dt) | KUninterpreted s dt <- newKinds]
             -- tuples. NB. Only declare the new sizes, old sizes persist.
             ++ concatMap declTuple (findTupleArities newKs)
+            -- sums
+            ++ (if containsSum   newKs then declSum   else [])
+            ++ (if containsMaybe newKs then declMaybe else [])
             -- constants
             ++ concatMap (declConst cfg) consts
             -- inputs
@@ -348,12 +408,16 @@
             ++ concat arrayDelayeds
             -- array setups
             ++ concat arraySetups
+            -- extra constraints
+            ++ map (\(isSoft, attr, v) -> "(assert" ++ (if isSoft then "-soft " else " ") ++ addAnnotations attr (cvtSV skolemMap v) ++ ")") (F.toList cstrs)
   where -- NB. The below setting of skolemMap to empty is OK, since we do
         -- not support queries in the context of skolemized variables
         skolemMap = M.empty
 
         rm = roundingMode cfg
 
+        newKinds = Set.toList newKs
+
         declInp (s, _) = "(declare-fun " ++ show s ++ " () " ++ svType s ++ ")"
 
         (arrayConstants, arrayDelayeds, arraySetups) = unzip3 $ map (declArray cfg afterAPush False consts skolemMap) arrs
@@ -362,6 +426,14 @@
         tableMap  = IM.fromList $ map mkTable allTables
           where mkTable (((t, _, _), _), _) = (t, "table" ++ show t)
 
+        -- If we need flattening in models, do emit the required lines if preset
+        settings
+          | any needsFlattening newKinds
+          = concat (catMaybes [supportsFlattenedModels solverCaps])
+          | True
+          = []
+          where solverCaps = capabilities (solver cfg)
+
 declDef :: SMTConfig -> SkolemMap -> TableMap -> (SV, SBVExpr) -> String
 declDef cfg skolemMap tableMap (s, expr) =
         case expr of
@@ -537,15 +609,15 @@
 
         supportsPB = supportsPseudoBooleans caps
 
-        bvOp     = all isBounded arguments
-        intOp    = any isInteger arguments
-        realOp   = any isReal    arguments
-        doubleOp = any isDouble  arguments
-        floatOp  = any isFloat   arguments
-        boolOp   = all isBoolean arguments
-        charOp   = any isChar    arguments
-        stringOp = any isString  arguments
-        listOp   = any isList    arguments
+        bvOp     = all isBounded   arguments
+        intOp    = any isUnbounded arguments
+        realOp   = any isReal      arguments
+        doubleOp = any isDouble    arguments
+        floatOp  = any isFloat     arguments
+        boolOp   = all isBoolean   arguments
+        charOp   = any isChar      arguments
+        stringOp = any isString    arguments
+        listOp   = any isList      arguments
 
         bad | intOp = error $ "SBV.SMTLib2: Unsupported operation on unbounded integers: " ++ show expr
             | True  = error $ "SBV.SMTLib2: Unsupported operation on real values: " ++ show expr
@@ -637,6 +709,30 @@
         lift1  o _ [x]    = "(" ++ o ++ " " ++ x ++ ")"
         lift1  o _ sbvs   = error $ "SBV.SMT.SMTLib2.sh.lift1: Unexpected arguments: "   ++ show (o, sbvs)
 
+        -- We fully qualify the constructor with their types to work around type checking issues
+        -- if the solver requires it, as specified by the 'supportsDTConstructorSigs' capability.
+        dtConstructor fld args res = result
+          where body = parIfArgs (unwords (fld : map ssv args))
+                parIfArgs r | null args = r
+                            | True      = "(" ++ r ++ ")"
+
+                constructor = body
+                withSig     = "(as " ++ constructor ++ " " ++ smtType res ++ ")"
+
+                result | supportsDTConstructorSigs caps = withSig
+                       | True                           = constructor
+
+        -- We fully qualify the accessors with their types to work around type checking issues
+        -- if the solver requires it, as specified by the 'supportsDTAccessorSigs' capability.
+        dtAccessor fld params res = result
+          where accessor = "(_ is " ++ fld ++ ")"
+
+                ps       = " (" ++ unwords (map smtType params) ++ ") "
+                withSig  = "(_ is (" ++ fld ++ ps ++ smtType res ++ "))"
+
+                result | supportsDTAccessorSigs caps = withSig
+                       | True                        = accessor
+
         sh (SBVApp Ite [a, b, c]) = "(ite " ++ ssv a ++ " " ++ ssv b ++ " " ++ ssv c ++ ")"
 
         sh (SBVApp (LkUp (t, aKnd, _, l) i e) [])
@@ -652,7 +748,10 @@
                               KChar              -> error "SBV.SMT.SMTLib2.cvtExp: unexpected char valued index"
                               KString            -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
                               KList k            -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected list valued: " ++ show k
+                              KSet  k            -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected set valued: " ++ show k
                               KTuple k           -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected tuple valued: " ++ show k
+                              KMaybe k           -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected maybe valued: " ++ show k
+                              KEither k1 k2      -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sum valued: " ++ show (k1, k2)
                               KUninterpreted s _ -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected uninterpreted valued index: " ++ s
 
                 lkUp = "(" ++ getTable tableMap t ++ " " ++ ssv i ++ ")"
@@ -671,7 +770,10 @@
                                 KChar              -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
                                 KString            -> error "SBV.SMT.SMTLib2.cvtExp: unexpected string valued index"
                                 KList k            -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sequence valued index: " ++ show k
+                                KSet  k            -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected set valued index: " ++ show k
                                 KTuple k           -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected tuple valued index: " ++ show k
+                                KMaybe k           -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected maybe valued index: " ++ show k
+                                KEither k1 k2      -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected sum valued index: " ++ show (k1, k2)
                                 KUninterpreted s _ -> error $ "SBV.SMT.SMTLib2.cvtExp: unexpected uninterpreted valued index: " ++ s
 
                 mkCnst = cvtCV rm . mkConstCV (kindOf i)
@@ -736,10 +838,33 @@
 
         sh (SBVApp (SeqOp op) args) = "(" ++ show op ++ " " ++ unwords (map ssv args) ++ ")"
 
-        sh (SBVApp (TupleConstructor 0)   [])    = "SBVTuple0"
+        sh (SBVApp (SetOp SetEqual)      args)   = "(= "      ++ unwords (map ssv args) ++ ")"
+        sh (SBVApp (SetOp SetMember)     [e, s]) = "(select " ++ ssv s ++ " " ++ ssv e ++ ")"
+        sh (SBVApp (SetOp SetInsert)     [e, s]) = "(store "  ++ ssv s ++ " " ++ ssv e ++ " true)"
+        sh (SBVApp (SetOp SetDelete)     [e, s]) = "(store "  ++ ssv s ++ " " ++ ssv e ++ " false)"
+        sh (SBVApp (SetOp SetIntersect)  args)   = "((_ map and) " ++ unwords (map ssv args) ++ ")"
+        sh (SBVApp (SetOp SetUnion)      args)   = "((_ map or) "  ++ unwords (map ssv args) ++ ")"
+        sh (SBVApp (SetOp SetSubset)     args)   = "(subset "      ++ unwords (map ssv args) ++ ")"
+        sh (SBVApp (SetOp SetDifference) args)   = "(difference "  ++ unwords (map ssv args) ++ ")"
+        sh (SBVApp (SetOp SetComplement) args)   = "((_ map not) " ++ unwords (map ssv args) ++ ")"
+
+        sh (SBVApp (TupleConstructor 0)   [])    = "mkSBVTuple0"
         sh (SBVApp (TupleConstructor n)   args)  = "(mkSBVTuple" ++ show n ++ " " ++ unwords (map ssv args) ++ ")"
         sh (SBVApp (TupleAccess      i n) [tup]) = "(proj_" ++ show i ++ "_SBVTuple" ++ show n ++ " " ++ ssv tup ++ ")"
 
+        sh (SBVApp (EitherConstructor k1 k2 False) [arg]) =       dtConstructor "left_SBVEither"  [arg] (KEither k1 k2)
+        sh (SBVApp (EitherConstructor k1 k2 True ) [arg]) =       dtConstructor "right_SBVEither" [arg] (KEither k1 k2)
+        sh (SBVApp (EitherIs          k1 k2 False) [arg]) = '(' : dtAccessor    "left_SBVEither"  [k1]  (KEither k1 k2) ++ " " ++ ssv arg ++ ")"
+        sh (SBVApp (EitherIs          k1 k2 True ) [arg]) = '(' : dtAccessor    "right_SBVEither" [k2]  (KEither k1 k2) ++ " " ++ ssv arg ++ ")"
+        sh (SBVApp (EitherAccess            False) [arg]) = "(get_left_SBVEither "  ++ ssv arg ++ ")"
+        sh (SBVApp (EitherAccess            True ) [arg]) = "(get_right_SBVEither " ++ ssv arg ++ ")"
+
+        sh (SBVApp (MaybeConstructor k False) [])    =       dtConstructor "nothing_SBVMaybe" []    (KMaybe k)
+        sh (SBVApp (MaybeConstructor k True)  [arg]) =       dtConstructor "just_SBVMaybe"    [arg] (KMaybe k)
+        sh (SBVApp (MaybeIs          k False) [arg]) = '(' : dtAccessor    "nothing_SBVMaybe" []    (KMaybe k) ++ " " ++ ssv arg ++ ")"
+        sh (SBVApp (MaybeIs          k True ) [arg]) = '(' : dtAccessor    "just_SBVMaybe"    [k]   (KMaybe k) ++ " " ++ ssv arg ++ ")"
+        sh (SBVApp MaybeAccess                [arg]) = "(get_just_SBVMaybe " ++ ssv arg ++ ")"
+
         sh inp@(SBVApp op args)
           | intOp, Just f <- lookup op smtOpIntTable
           = f True (map ssv args)
@@ -885,10 +1010,6 @@
   = "(" ++ cast kFrom kTo input ++ ")"
   where addRM a s = s ++ " " ++ rm ++ " " ++ a
 
-        absRM a s = "ite (fp.isNegative " ++ a ++ ") (" ++ cvt1 ++ ") (" ++ cvt2 ++ ")"
-          where cvt1 = "bvneg (" ++ s ++ " " ++ rm ++ " (fp.abs " ++ a ++ "))"
-                cvt2 =              s ++ " " ++ rm ++ " "         ++ a
-
         -- To go and back from Ints, we detour through reals
         cast KUnbounded         KFloat             a = "(_ to_fp 8 24) "  ++ rm ++ " (to_real " ++ a ++ ")"
         cast KUnbounded         KDouble            a = "(_ to_fp 11 53) " ++ rm ++ " (to_real " ++ a ++ ")"
@@ -910,10 +1031,11 @@
         cast KDouble            KDouble            a = addRM a "(_ to_fp 11 53)"
 
         -- From float/double
-        cast KFloat             (KBounded False m) a = absRM a $ "(_ fp.to_ubv " ++ show m ++ ")"
-        cast KDouble            (KBounded False m) a = absRM a $ "(_ fp.to_ubv " ++ show m ++ ")"
+        cast KFloat             (KBounded False m) a = addRM a $ "(_ fp.to_ubv " ++ show m ++ ")"
+        cast KDouble            (KBounded False m) a = addRM a $ "(_ fp.to_ubv " ++ show m ++ ")"
         cast KFloat             (KBounded True  m) a = addRM a $ "(_ fp.to_sbv " ++ show m ++ ")"
         cast KDouble            (KBounded True  m) a = addRM a $ "(_ fp.to_sbv " ++ show m ++ ")"
+
         cast KFloat             KReal              a = "fp.to_real" ++ " " ++ a
         cast KDouble            KReal              a = "fp.to_real" ++ " " ++ a
 
diff --git a/Data/SBV/SMT/SMTLibNames.hs b/Data/SBV/SMT/SMTLibNames.hs
--- a/Data/SBV/SMT/SMTLibNames.hs
+++ b/Data/SBV/SMT/SMTLibNames.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.SMT.SMTLibNames
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/SMT/Utils.hs b/Data/SBV/SMT/Utils.hs
--- a/Data/SBV/SMT/Utils.hs
+++ b/Data/SBV/SMT/Utils.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.SMT.Utils
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -26,12 +26,15 @@
 
 import qualified Control.Exception as C
 
+import Control.Monad.Trans (MonadIO, liftIO)
+
 import Data.SBV.Core.Data
 import Data.SBV.Core.Symbolic (QueryContext)
 import Data.SBV.Utils.Lib (joinArgs)
 
 import Data.List (intercalate)
-import qualified Data.Set as Set (Set)
+import qualified Data.Set      as Set (Set)
+import qualified Data.Sequence as S   (Seq)
 
 import System.Exit (ExitCode(..))
 
@@ -48,20 +51,21 @@
                        -> [(String, SBVType)]                           -- ^ uninterpreted functions/constants
                        -> [(String, [String])]                          -- ^ user given axioms
                        -> SBVPgm                                        -- ^ assignments
-                       -> [(Bool, [(String, String)], SV)]              -- ^ extra constraints
+                       -> S.Seq (Bool, [(String, String)], SV)          -- ^ extra constraints
                        -> SV                                            -- ^ output variable
                        -> SMTConfig                                     -- ^ configuration
                        -> a
 
 -- | An instance of SMT-Lib converter; instantiated for SMT-Lib v1 and v2. (And potentially for newer versions in the future.)
-type SMTLibIncConverter a =  [NamedSymVar]                -- ^ inputs
-                          -> Set.Set Kind                 -- ^ new kinds
-                          -> [(SV, CV)]                   -- ^ constants
-                          -> [(Int, ArrayInfo)]           -- ^ newly created arrays
-                          -> [((Int, Kind, Kind), [SV])]  -- ^ newly created tables
-                          -> [(String, SBVType)]          -- ^ newly created uninterpreted functions/constants
-                          -> SBVPgm                       -- ^ assignments
-                          -> SMTConfig                    -- ^ configuration
+type SMTLibIncConverter a =  [NamedSymVar]                         -- ^ inputs
+                          -> Set.Set Kind                          -- ^ new kinds
+                          -> [(SV, CV)]                            -- ^ constants
+                          -> [(Int, ArrayInfo)]                    -- ^ newly created arrays
+                          -> [((Int, Kind, Kind), [SV])]           -- ^ newly created tables
+                          -> [(String, SBVType)]                   -- ^ newly created uninterpreted functions/constants
+                          -> SBVPgm                                -- ^ assignments
+                          -> S.Seq (Bool, [(String, String)], SV)  -- ^ extra constraints
+                          -> SMTConfig                             -- ^ configuration
                           -> a
 
 -- | Create an annotated term
@@ -93,11 +97,11 @@
 alignWithPrefix pre tag multi = intercalate "\n" $ zipWith (++) (tag : repeat (pre ++ replicate (length tag - length pre) ' ')) (filter (not . null) (lines multi))
 
 -- | Diagnostic message when verbose
-debug :: SMTConfig -> [String] -> IO ()
+debug :: MonadIO m => SMTConfig -> [String] -> m ()
 debug cfg
   | not (verbose cfg)             = const (return ())
-  | Just f <- redirectVerbose cfg = mapM_ (appendFile f . (++ "\n"))
-  | True                          = mapM_ putStrLn
+  | Just f <- redirectVerbose cfg = liftIO . mapM_ (appendFile f . (++ "\n"))
+  | True                          = liftIO . mapM_ putStrLn
 
 -- | In case the SMT-Lib solver returns a response over multiple lines, compress them so we have
 -- each S-Expression spanning only a single line.
diff --git a/Data/SBV/Set.hs b/Data/SBV/Set.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Set.hs
@@ -0,0 +1,513 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Set
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A collection of set utilities, useful when working with symbolic sets.
+-- To the extent possible, the functions in this module follow those
+-- of "Data.Set" so importing qualified is the recommended workflow.
+--
+-- Note that unlike "Data.Set", SBV sets can be infinite, represented
+-- as a complement of some finite set. This means that a symbolic set
+-- is either finite, or its complement is finite. (If the underlying
+-- domain is finite, then obviously both the set itself and its complement
+-- will always be finite.) Therefore, there are some differences in the API
+-- from Haskell sets. For instance, you can take the complement of any set,
+-- which is something you cannot do in Haskell! Conversely, you cannot compute
+-- the size of a symbolic set (as it can be infinite!), nor you can turn
+-- it into a list or necessarily enumerate its elements.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+module Data.SBV.Set (
+        -- * Constructing sets
+          empty, full, universal, singleton, fromList, complement
+
+        -- * Equality of sets
+        -- $setEquality
+
+        -- * Insertion and deletion
+        , insert, delete
+
+        -- * Query
+        , member, notMember, null, isEmpty, isFull, isUniversal, isSubsetOf, isProperSubsetOf, disjoint
+
+        -- * Combinations
+        , union, unions, intersection, intersections, difference, (\\)
+
+        ) where
+
+import Prelude hiding (null)
+
+import Data.Proxy (Proxy(Proxy))
+import qualified Data.Set as Set
+
+import Data.SBV.Core.Data
+import Data.SBV.Core.Model    ((.==), (./=))
+import Data.SBV.Core.Symbolic (SetOp(..))
+
+-- For doctest use only
+--
+-- $setup
+-- >>> import Data.SBV.Core.Model
+-- >>> import Data.SBV.Provers.Prover
+-- >>> :set -XScopedTypeVariables
+
+-- | Empty set.
+--
+-- >>> empty :: SSet Integer
+-- {} :: {SInteger}
+empty :: forall a. HasKind a => SSet a
+empty = SBV $ SVal k $ Left $ CV k $ CSet $ RegularSet Set.empty
+  where k = KSet $ kindOf (Proxy @a)
+
+-- | Full set.
+--
+-- >>> full :: SSet Integer
+-- U :: {SInteger}
+--
+-- Note that the universal set over a type is represented by the letter @U@.
+full :: forall a. HasKind a => SSet a
+full = SBV $ SVal k $ Left $ CV k $ CSet $ ComplementSet Set.empty
+  where k = KSet $ kindOf (Proxy @a)
+
+-- | Synonym for 'full'.
+universal :: forall a. HasKind a => SSet a
+universal = full
+
+-- | Singleton list.
+--
+-- >>> singleton 2 :: SSet Integer
+-- {2} :: {SInteger}
+singleton :: forall a. (Ord a, SymVal a) => SBV a -> SSet a
+singleton = (`insert` (empty :: SSet a))
+
+-- | Conversion from a list.
+--
+-- >>> fromList ([] :: [Integer])
+-- {} :: {SInteger}
+-- >>> fromList [1,2,3]
+-- {1,2,3} :: {SInteger}
+-- >>> fromList [5,5,5,12,12,3]
+-- {3,5,12} :: {SInteger}
+fromList :: forall a. (Ord a, SymVal a) => [a] -> SSet a
+fromList = literal . RegularSet . Set.fromList
+
+-- | Complement.
+--
+-- >>> empty .== complement (full :: SSet Integer)
+-- True
+--
+-- Complementing twice gets us back the original set:
+--
+-- >>> prove $ \(s :: SSet Integer) -> complement (complement s) .== s
+-- Q.E.D.
+complement :: forall a. (Ord a, SymVal a) => SSet a -> SSet a
+complement ss
+  | Just (RegularSet rs) <- unliteral ss
+  = literal $ ComplementSet rs
+  | Just (ComplementSet cs) <- unliteral ss
+  = literal $ RegularSet cs
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = KSet (kindOf (Proxy @a))
+
+        r st = do svs <- sbvToSV st ss
+                  newExpr st k $ SBVApp (SetOp SetComplement) [svs]
+
+-- | Insert an element into a set.
+--
+-- Insertion is order independent:
+--
+-- >>> prove $ \x y (s :: SSet Integer) -> x `insert` (y `insert` s) .== y `insert` (x `insert` s)
+-- Q.E.D.
+--
+-- Deletion after insertion is not necessarily identity:
+--
+-- >>> prove $ \x (s :: SSet Integer) -> x `delete` (x `insert` s) .== s
+-- Falsifiable. Counter-example:
+--   s0 =   0 :: Integer
+--   s1 = {0} :: {Integer}
+--
+-- But the above is true if the element isn't in the set to start with:
+--
+-- >>> prove $ \x (s :: SSet Integer) -> x `notMember` s .=> x `delete` (x `insert` s) .== s
+-- Q.E.D.
+--
+-- Insertion into a full set does nothing:
+--
+-- >>> prove $ \x -> insert x full .== (full :: SSet Integer)
+-- Q.E.D.
+insert :: forall a. (Ord a, SymVal a) => SBV a -> SSet a -> SSet a
+insert se ss
+  -- Case 1: Constant regular set, just add it:
+  | Just e <- unliteral se, Just (RegularSet rs) <- unliteral ss
+  = literal $ RegularSet $ e `Set.insert` rs
+
+  -- Case 2: Constant complement set, with element in the complement, just remove it:
+  | Just e <- unliteral se, Just (ComplementSet cs) <- unliteral ss, e `Set.member` cs
+  = literal $ ComplementSet $ e `Set.delete` cs
+
+  -- Otherwise, go symbolic
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where ka = kindOf (Proxy @a)
+        k  = KSet ka
+
+        r st = do svs <- sbvToSV st ss
+                  sve <- sbvToSV st se
+                  newExpr st k $ SBVApp (SetOp SetInsert) [sve, svs]
+
+-- | Delete an element from a set.
+--
+-- Deletion is order independent:
+--
+-- >>> prove $ \x y (s :: SSet Integer) -> x `delete` (y `delete` s) .== y `delete` (x `delete` s)
+-- Q.E.D.
+--
+-- Insertion after deletion is not necessarily identity:
+--
+-- >>> prove $ \x (s :: SSet Integer) -> x `insert` (x `delete` s) .== s
+-- Falsifiable. Counter-example:
+--   s0 =  0 :: Integer
+--   s1 = {} :: {Integer}
+--
+-- But the above is true if the element is in the set to start with:
+--
+-- >>> prove $ \x (s :: SSet Integer) -> x `member` s .=> x `insert` (x `delete` s) .== s
+-- Q.E.D.
+--
+-- Deletion from an empty set does nothing:
+--
+-- >>> prove $ \x -> delete x empty .== (empty :: SSet Integer)
+-- Q.E.D.
+delete :: forall a. (Ord a, SymVal a) => SBV a -> SSet a -> SSet a
+delete se ss
+  -- Case 1: Constant regular set, just remove it:
+  | Just e <- unliteral se, Just (RegularSet rs) <- unliteral ss
+  = literal $ RegularSet $ e `Set.delete` rs
+
+  -- Case 2: Constant complement set, with element missing in the complement, just add it:
+  | Just e <- unliteral se, Just (ComplementSet cs) <- unliteral ss, e `Set.notMember` cs
+  = literal $ ComplementSet $ e `Set.insert` cs
+
+  -- Otherwise, go symbolic
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where ka = kindOf (Proxy @a)
+        k  = KSet ka
+
+        r st = do svs <- sbvToSV st ss
+                  sve <- sbvToSV st se
+                  newExpr st k $ SBVApp (SetOp SetDelete) [sve, svs]
+
+-- | Test for membership.
+--
+-- >>> prove $ \x -> x `member` singleton (x :: SInteger)
+-- Q.E.D.
+--
+-- >>> prove $ \x (s :: SSet Integer) -> x `member` (x `insert` s)
+-- Q.E.D.
+--
+-- >>> prove $ \x -> x `member` (full :: SSet Integer)
+-- Q.E.D.
+member :: (Ord a, SymVal a) => SBV a -> SSet a -> SBool
+member se ss
+  -- Case 1: Constant regular set, just check:
+  | Just e <- unliteral se, Just (RegularSet rs) <- unliteral ss
+  = literal $ e `Set.member` rs
+
+  -- Case 2: Constant complement set, check for non-member
+  | Just e <- unliteral se, Just (ComplementSet cs) <- unliteral ss
+  = literal $ e `Set.notMember` cs
+
+  -- Otherwise, go symbolic
+  | True
+  = SBV $ SVal KBool $ Right $ cache r
+  where r st = do svs <- sbvToSV st ss
+                  sve <- sbvToSV st se
+                  newExpr st KBool $ SBVApp (SetOp SetMember) [sve, svs]
+
+-- | Test for non-membership.
+--
+-- >>> prove $ \x -> x `notMember` observe "set" (singleton (x :: SInteger))
+-- Falsifiable. Counter-example:
+--   set = {0} :: {Integer}
+--   s0  =   0 :: Integer
+--
+-- >>> prove $ \x (s :: SSet Integer) -> x `notMember` (x `delete` s)
+-- Q.E.D.
+--
+-- >>> prove $ \x -> x `notMember` (empty :: SSet Integer)
+-- Q.E.D.
+notMember :: (Ord a, SymVal a) => SBV a -> SSet a -> SBool
+notMember se ss = sNot $ member se ss
+
+-- | Is this the empty set?
+--
+-- >>> null (empty :: SSet Integer)
+-- True
+--
+-- >>> prove $ \x -> null (x `delete` singleton (x :: SInteger))
+-- Q.E.D.
+--
+-- >>> prove $ null (full :: SSet Integer)
+-- Falsifiable
+--
+-- Note how we have to call `Data.SBV.prove` in the last case since dealing
+-- with infinite sets requires a call to the solver and cannot be
+-- constant folded.
+null :: HasKind a => SSet a -> SBool
+null = (.== empty)
+
+-- | Synonym for 'Data.SBV.Set.null'.
+isEmpty :: HasKind a => SSet a -> SBool
+isEmpty = null
+
+-- | Is this the full set?
+--
+-- >>> prove $ isFull (empty :: SSet Integer)
+-- Falsifiable
+--
+-- >>> prove $ \x -> isFull (observe "set" (x `delete` (full :: SSet Integer)))
+-- Falsifiable. Counter-example:
+--   set = U - {0} :: {Integer}
+--   s0  =       0 :: Integer
+--
+-- >>> isFull (full :: SSet Integer)
+-- True
+--
+-- Note how we have to call `Data.SBV.prove` in the first case since dealing
+-- with infinite sets requires a call to the solver and cannot be
+-- constant folded.
+isFull :: HasKind a => SSet a -> SBool
+isFull = (.== full)
+
+-- | Synonym for 'Data.SBV.Set.isFull'.
+isUniversal :: HasKind a => SSet a -> SBool
+isUniversal = isFull
+
+-- | Subset test.
+--
+-- >>> prove $ empty `isSubsetOf` (full :: SSet Integer)
+-- Q.E.D.
+--
+-- >>> prove $ \x (s :: SSet Integer) -> s `isSubsetOf` (x `insert` s)
+-- Q.E.D.
+--
+-- >>> prove $ \x (s :: SSet Integer) -> (x `delete` s) `isSubsetOf` s
+-- Q.E.D.
+isSubsetOf :: (Ord a, SymVal a) => SSet a -> SSet a -> SBool
+isSubsetOf sa sb
+  -- Case 1: Constant regular sets, just check:
+  | Just (RegularSet a) <- unliteral sa, Just (RegularSet b) <- unliteral sb
+  = literal $ a `Set.isSubsetOf` b
+
+  -- Case 2: Constant complement sets, check in the reverse direction:
+  | Just (ComplementSet a) <- unliteral sa, Just (ComplementSet b) <- unliteral sb
+  = literal $ b `Set.isSubsetOf` a
+
+  -- Otherwise, go symbolic
+  | True
+  = SBV $ SVal KBool $ Right $ cache r
+  where r st = do sva <- sbvToSV st sa
+                  svb <- sbvToSV st sb
+                  newExpr st KBool $ SBVApp (SetOp SetSubset) [sva, svb]
+
+-- | Proper subset test.
+--
+-- >>> prove $ empty `isProperSubsetOf` (full :: SSet Integer)
+-- Q.E.D.
+--
+-- >>> prove $ \x (s :: SSet Integer) -> s `isProperSubsetOf` (x `insert` s)
+-- Falsifiable. Counter-example:
+--   s0 =       0 :: Integer
+--   s1 = U - {1} :: {Integer}
+--
+-- >>> prove $ \x (s :: SSet Integer) -> x `notMember` s .=> s `isProperSubsetOf` (x `insert` s)
+-- Q.E.D.
+--
+-- >>> prove $ \x (s :: SSet Integer) -> (x `delete` s) `isProperSubsetOf` s
+-- Falsifiable. Counter-example:
+--   s0 =   0 :: Integer
+--   s1 = {1} :: {Integer}
+--
+-- >>> prove $ \x (s :: SSet Integer) -> x `member` s .=> (x `delete` s) `isProperSubsetOf` s
+-- Q.E.D.
+isProperSubsetOf :: (Ord a, SymVal a) => SSet a -> SSet a -> SBool
+isProperSubsetOf a b = a `isSubsetOf` b .&& a ./= b
+
+-- | Disjoint test.
+--
+-- >>> disjoint (fromList [2,4,6])   (fromList [1,3])
+-- True
+-- >>> disjoint (fromList [2,4,6,8]) (fromList [2,3,5,7])
+-- False
+-- >>> disjoint (fromList [1,2])     (fromList [1,2,3,4])
+-- False
+-- >>> prove $ \(s :: SSet Integer) -> s `disjoint` complement s
+-- Q.E.D.
+-- >>> allSat $ \(s :: SSet Integer) -> s `disjoint` s
+-- Solution #1:
+--   s0 = {} :: {Integer}
+-- This is the only solution.
+--
+-- The last example is particularly interesting: The empty set is the
+-- only set where `disjoint` is not reflexive!
+--
+-- Note that disjointness of a set from its complement is guaranteed
+-- by the fact that all types are inhabited; an implicit assumption
+-- we have in classic logic which is also enjoyed by Haskell due to
+-- the presence of bottom!
+disjoint :: (Ord a, SymVal a) => SSet a -> SSet a -> SBool
+disjoint a b = a `intersection` b .== empty
+
+-- | Union.
+--
+-- >>> union (fromList [1..10]) (fromList [5..15]) .== (fromList [1..15] :: SSet Integer)
+-- True
+-- >>> prove $ \(a :: SSet Integer) b -> a `union` b .== b `union` a
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) b c -> a `union` (b `union` c) .== (a `union` b) `union` c
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> a `union` full .== full
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> a `union` empty .== a
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> a `union` complement a .== full
+-- Q.E.D.
+union :: (Ord a, SymVal a) => SSet a -> SSet a -> SSet a
+union sa sb
+  -- Case 1: Constant regular sets, just compute
+  | Just (RegularSet a) <- unliteral sa, Just (RegularSet b) <- unliteral sb
+  = literal $ RegularSet $ a `Set.union` b
+
+  -- Case 2: Constant complement sets, complement the intersection:
+  | Just (ComplementSet a) <- unliteral sa, Just (ComplementSet b) <- unliteral sb
+  = literal $ ComplementSet $ a `Set.intersection` b
+
+  -- Otherwise, go symbolic
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf sa
+        r st = do sva <- sbvToSV st sa
+                  svb <- sbvToSV st sb
+                  newExpr st k $ SBVApp (SetOp SetUnion) [sva, svb]
+
+-- | Unions. Equivalent to @'foldr' 'union' 'empty'@.
+--
+-- >>> prove $ unions [] .== (empty :: SSet Integer)
+-- Q.E.D.
+unions :: (Ord a, SymVal a) => [SSet a] -> SSet a
+unions = foldr union empty
+
+-- | Intersection.
+--
+-- >>> intersection (fromList [1..10]) (fromList [5..15]) .== (fromList [5..10] :: SSet Integer)
+-- True
+-- >>> prove $ \(a :: SSet Integer) b -> a `intersection` b .== b `intersection` a
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) b c -> a `intersection` (b `intersection` c) .== (a `intersection` b) `intersection` c
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> a `intersection` full .== a
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> a `intersection` empty .== empty
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> a `intersection` complement a .== empty
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) b -> a `disjoint` b .=> a `intersection` b .== empty
+-- Q.E.D.
+intersection :: (Ord a, SymVal a) => SSet a -> SSet a -> SSet a
+intersection sa sb
+  -- Case 1: Constant regular sets, just compute
+  | Just (RegularSet a) <- unliteral sa, Just (RegularSet b) <- unliteral sb
+  = literal $ RegularSet $ a `Set.intersection` b
+
+  -- Case 2: Constant complement sets, complement the union:
+  | Just (ComplementSet a) <- unliteral sa, Just (ComplementSet b) <- unliteral sb
+  = literal $ ComplementSet $ a `Set.union` b
+
+  -- Otherwise, go symbolic
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf sa
+        r st = do sva <- sbvToSV st sa
+                  svb <- sbvToSV st sb
+                  newExpr st k $ SBVApp (SetOp SetIntersect) [sva, svb]
+
+-- | Intersections. Equivalent to @'foldr' 'intersection' 'full'@. Note that
+-- Haskell's 'Data.Set' does not support this operation as it does not have a
+-- way of representing universal sets.
+--
+-- >>> prove $ intersections [] .== (full :: SSet Integer)
+-- Q.E.D.
+intersections :: (Ord a, SymVal a) => [SSet a] -> SSet a
+intersections = foldr intersection full
+
+-- | Difference.
+--
+-- >>> prove $ \(a :: SSet Integer) -> empty `difference` a .== empty
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> a `difference` empty .== a
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> full `difference` a .== complement a
+-- Q.E.D.
+-- >>> prove $ \(a :: SSet Integer) -> a `difference` a .== empty
+-- Q.E.D.
+difference :: (Ord a, SymVal a) => SSet a -> SSet a -> SSet a
+difference sa sb
+  -- Only constant fold the regular case, others are left symbolic
+  | Just (RegularSet a) <- unliteral sa, Just (RegularSet b) <- unliteral sb
+  = literal $ RegularSet $ a `Set.difference` b
+
+  -- Otherwise, go symbolic
+  | True
+  = SBV $ SVal k $ Right $ cache r
+  where k = kindOf sa
+        r st = do sva <- sbvToSV st sa
+                  svb <- sbvToSV st sb
+                  newExpr st k $ SBVApp (SetOp SetDifference) [sva, svb]
+
+-- | Synonym for 'Data.SBV.Set.difference'.
+infixl 9 \\
+(\\) :: (Ord a, SymVal a) => SSet a -> SSet a -> SSet a
+(\\) = difference
+
+{- $setEquality
+We can compare sets for equality:
+
+>>> empty .== (empty :: SSet Integer)
+True
+>>> full .== (full :: SSet Integer)
+True
+>>> full ./= (full :: SSet Integer)
+False
+>>> sat $ \(x::SSet (Maybe Integer)) y z -> distinct [x, y, z]
+Satisfiable. Model:
+  s0 = U - {Nothing} :: {Maybe Integer}
+  s1 =            {} :: {Maybe Integer}
+  s2 =             U :: {Maybe Integer}
+
+However, if we compare two sets that are constructed as regular or in the complement
+form, we have to use a proof to establish equality:
+
+>>> prove $ full .== (empty :: SSet Integer)
+Falsifiable
+
+The reason for this is that there is no way in Haskell to compare an infinite
+set to any other set, as infinite sets are not representable at all! So, we have
+to delay the judgment to the SMT solver. If you try to constant fold, you
+will get:
+
+>>> full .== (empty :: SSet Integer)
+<symbolic> :: SBool
+
+indicating that the result is a symbolic value that needs a decision
+procedure to be determined!
+-}
diff --git a/Data/SBV/String.hs b/Data/SBV/String.hs
--- a/Data/SBV/String.hs
+++ b/Data/SBV/String.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.String
--- Author    : Joel Burget, Levent Erkok
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -23,7 +24,7 @@
         -- * Length, emptiness
           length, null
         -- * Deconstructing/Reconstructing
-        , head, tail, uncons, init, singleton, strToStrAt, strToCharAt, (.!!), implode, concat, (.:), nil, (.++)
+        , head, tail, uncons, init, singleton, strToStrAt, strToCharAt, (.!!), implode, concat, (.:), snoc, nil, (.++)
         -- * Containment
         , isInfixOf, isSuffixOf, isPrefixOf
         -- * Substrings
@@ -130,7 +131,7 @@
 -- Q.E.D.
 -- >>> sat $ \s -> length s .>= 2 .&& strToStrAt s 0 ./= strToStrAt s (length s - 1)
 -- Satisfiable. Model:
---   s0 = "\NUL\NUL\128" :: String
+--   s0 = "\NUL\NUL\DLE" :: String
 strToStrAt :: SString -> SInteger -> SString
 strToStrAt s offset = subStr s offset 1
 
@@ -178,6 +179,10 @@
 (.:) :: SChar -> SString -> SString
 c .: cs = singleton c .++ cs
 
+-- | Append an element
+snoc :: SString -> SChar -> SString
+s `snoc` c = s .++ singleton c
+
 -- | Empty string. This value has the property that it's the only string with length 0:
 --
 -- >>> prove $ \l -> length l .== 0 .<=> l .== nil
@@ -317,8 +322,8 @@
 -- Q.E.D.
 -- >>> prove $ \s i -> i .> 0 .&& i .< length s .=> indexOf s (subStr s i 1) .== i
 -- Falsifiable. Counter-example:
---   s0 = " \NUL\NUL\NUL\NUL\NUL" :: String
---   s1 =                       3 :: Integer
+--   s0 = "\128\NUL\NUL" :: String
+--   s1 =              2 :: Integer
 -- >>> prove $ \s1 s2 -> length s2 .> length s1 .=> indexOf s1 s2 .== -1
 -- Q.E.D.
 indexOf :: SString -> SString -> SInteger
diff --git a/Data/SBV/Tools/BMC.hs b/Data/SBV/Tools/BMC.hs
--- a/Data/SBV/Tools/BMC.hs
+++ b/Data/SBV/Tools/BMC.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.BMC
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -49,7 +49,7 @@
         -> IO (Either String (Int, [res]))
 bmcWith cfg mbLimit chatty setup initial trans goal
   = runSMTWith cfg $ do setup
-                        query $ do state <- fresh
+                        query $ do state <- create
                                    constrain $ initial state
                                    go 0 state []
    where go i _ _
@@ -61,11 +61,11 @@
                                   cs <- checkSat
                                   case cs of
                                     Sat   -> do when chatty $ io $ putStrLn $ "BMC: Solution found at iteration " ++ show i
-                                                ms <- mapM extract (curState : sofar)
+                                                ms <- mapM project (curState : sofar)
                                                 return $ Right (i, reverse ms)
                                     Unk   -> do when chatty $ io $ putStrLn $ "BMC: Backend solver said unknown at iteration " ++ show  i
                                                 return $ Left $ "BMC: Solver said unknown in iteration " ++ show i
                                     Unsat -> do pop 1
-                                                nextState <- fresh
+                                                nextState <- create
                                                 constrain $ sAny (nextState .==) (trans curState)
                                                 go (i+1) nextState (curState : sofar)
diff --git a/Data/SBV/Tools/BoundedFix.hs b/Data/SBV/Tools/BoundedFix.hs
--- a/Data/SBV/Tools/BoundedFix.hs
+++ b/Data/SBV/Tools/BoundedFix.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.BoundedFix
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -49,7 +49,14 @@
 -- >>> prove $ \n -> n .== 10 .=> bfac n .== 3628800
 -- Falsifiable. Counter-example:
 --   s0 = 10 :: Integer
+-- <BLANKLINE>
+--   fac :: Integer -> Integer
+--   fac _ = 2
 --
+-- The counter-example is telling us how it instantiated the function @fac@ when the recursion
+-- bottomed out: It simply made it return @2@ for all arguments at that point, which provides
+-- the (unintended) counter-example.
+--
 -- By design, if a function defined via `bfix` is given a concrete argument, it will unroll
 -- the recursion as much as necessary to complete the call (which can of course diverge). The bound
 -- only applies if the given argument is symbolic. This fact can be used to observe concrete
@@ -60,11 +67,15 @@
 --   bfac_10 = 3628800 :: Integer
 --   bfac_n  = 7257600 :: Integer
 --   s0      =      10 :: Integer
+-- <BLANKLINE>
+--   fac :: Integer -> Integer
+--   fac _ = 2
 --
--- Here, we see that the SMT solver must have decided to assign the value @2@ in the final call just
--- as it was reaching the base case, and thus got the final result incorrect. (Note
--- that @7257600 = 2 * 3628800@.) A wrapper algorithm can then assert the actual value of
--- @bfac 10@ here as an extra constraint and can search for "deeper bugs."
+-- Here, we see further evidence that the SMT solver must have decided to assign the
+-- value @2@ in the final call just as it was reaching the base case, and thus got the
+-- final result incorrect. (Note that @7257600 = 2 * 3628800@.) A wrapper algorithm can
+-- then assert the actual value of @bfac 10@ here as an extra constraint and can
+-- search for "deeper bugs."
 bfix :: (SymVal a, Uninterpreted (SBV a -> r)) => Int -> String -> ((SBV a -> r) -> (SBV a -> r)) -> SBV a -> r
 bfix bound nm f x
   | isConcrete x = g x
diff --git a/Data/SBV/Tools/BoundedList.hs b/Data/SBV/Tools/BoundedList.hs
--- a/Data/SBV/Tools/BoundedList.hs
+++ b/Data/SBV/Tools/BoundedList.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.BoundedList
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -67,11 +67,11 @@
         go i b s = lcase s (return b) (\h t -> do { fbh <- f b h; go (i-1) fbh t })
 
 -- | Bounded sum.
-bsum :: (SymVal a, Num a) => Int -> SList a -> SBV a
+bsum :: (SymVal a, Num a, Ord a) => Int -> SList a -> SBV a
 bsum i = bfoldl i (+) 0
 
 -- | Bounded product.
-bprod :: (SymVal a, Num a) => Int -> SList a -> SBV a
+bprod :: (SymVal a, Num a, Ord a) => Int -> SList a -> SBV a
 bprod i = bfoldl i (*) 1
 
 -- | Bounded map.
@@ -104,11 +104,11 @@
 ball i f = band i . bmap i f
 
 -- | Bounded maximum. Undefined if list is empty.
-bmaximum :: SymVal a => Int -> SList a -> SBV a
+bmaximum :: (Ord a, SymVal a) => Int -> SList a -> SBV a
 bmaximum i l = bfoldl (i-1) smax (L.head l) (L.tail l)
 
 -- | Bounded minimum. Undefined if list is empty.
-bminimum :: SymVal a => Int -> SList a -> SBV a
+bminimum :: (Ord a, SymVal a) => Int -> SList a -> SBV a
 bminimum i l = bfoldl (i-1) smin (L.head l) (L.tail l)
 
 -- | Bounded zipWith
@@ -120,7 +120,7 @@
                           (f (L.head xs) (L.head ys) .: go (i-1) (L.tail xs) (L.tail ys))
 
 -- | Bounded element check
-belem :: SymVal a => Int -> SBV a -> SList a -> SBool
+belem :: (Eq a, SymVal a) => Int -> SBV a -> SList a -> SBool
 belem i e = bany i (e .==)
 
 -- | Bounded reverse
@@ -134,12 +134,12 @@
         go i s = lcase s b (\h t -> f h t (go (i-1) t))
 
 -- | Insert an element into a sorted list (not exported).
-binsert :: SymVal a => Int -> SBV a -> SList a -> SList a
+binsert :: (Ord a, SymVal a) => Int -> SBV a -> SList a -> SList a
 binsert cnt a = bpara cnt f (L.singleton a)
   where f sortedHd sortedTl sortedTl' = ite (a .< sortedHd)
                                             (a .: sortedHd .: sortedTl)
                                             (sortedHd .: sortedTl')
 
 -- | Bounded insertion sort
-bsort :: SymVal a => Int -> SList a -> SList a
+bsort :: (Ord a, SymVal a) => Int -> SList a -> SList a
 bsort cnt = bfoldr cnt (binsert cnt) []
diff --git a/Data/SBV/Tools/CodeGen.hs b/Data/SBV/Tools/CodeGen.hs
--- a/Data/SBV/Tools/CodeGen.hs
+++ b/Data/SBV/Tools/CodeGen.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.CodeGen
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/Tools/GenTest.hs b/Data/SBV/Tools/GenTest.hs
--- a/Data/SBV/Tools/GenTest.hs
+++ b/Data/SBV/Tools/GenTest.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.GenTest
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -25,6 +25,8 @@
 
 import Data.SBV.Utils.PrettyNum
 
+import qualified Data.Foldable as F (toList)
+
 -- | Type of test vectors (abstract)
 newtype TestVectors = TV [([CV], [CV])]
 
@@ -44,9 +46,9 @@
          | i == n = return $ TV $ reverse sofar
          | True   = do t <- tc
                        gen (i+1) (t:sofar)
-        tc = do (_, Result {resTraces=tvals, resConsts=cs, resConstraints=cstrs, resOutputs=os}) <- runSymbolic Concrete (m >>= output)
+        tc = do (_, Result {resTraces=tvals, resConsts=cs, resConstraints=cstrs, resOutputs=os}) <- runSymbolic (Concrete Nothing) (m >>= output)
                 let cval = fromMaybe (error "Cannot generate tests in the presence of uninterpeted constants!") . (`lookup` cs)
-                    cond = and [cvToBool (cval v) | (False, _, v) <- cstrs] -- Only pick-up "hard" constraints, as indicated by False in the fist component
+                    cond = and [cvToBool (cval v) | (False, _, v) <- F.toList cstrs] -- Only pick-up "hard" constraints, as indicated by False in the fist component
                 if cond
                    then return (map snd tvals, map cval os)
                    else tc   -- try again, with the same set of constraints
@@ -130,6 +132,7 @@
                  KString             -> error "SBV.renderTest: Unsupported string"
                  KReal               -> error $ "SBV.renderTest: Unsupported real valued test value: " ++ show cv
                  KList es            -> error $ "SBV.renderTest: Unsupported list valued test: [" ++ show es ++ "]"
+                 KSet  es            -> error $ "SBV.renderTest: Unsupported set valued test: {" ++ show es ++ "}"
                  KUninterpreted us _ -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
                  _                   -> error $ "SBV.renderTest: Unexpected CV: " ++ show cv
 
@@ -143,8 +146,11 @@
                   KString             -> error "SBV.renderTest: Unsupported string"
                   KReal               -> let CAlgReal w = cvVal cv in algRealToHaskell w
                   KList es            -> error $ "SBV.renderTest: Unsupported list valued sort: [" ++ show es ++ "]"
+                  KSet  es            -> error $ "SBV.renderTest: Unsupported set valued sort: {" ++ show es ++ "}"
                   KUninterpreted us _ -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
                   k@KTuple{}          -> error $ "SBV.renderTest: Unsupported tuple: " ++ show k
+                  k@KMaybe{}          -> error $ "SBV.renderTest: Unsupported maybe: " ++ show k
+                  k@KEither{}         -> error $ "SBV.renderTest: Unsupported sum: " ++ show k
 
 c :: String -> [([CV], [CV])] -> String
 c n vs = intercalate "\n" $
@@ -219,6 +225,7 @@
                         KBounded True  16   -> "SInt16"
                         KBounded True  32   -> "SInt32"
                         KBounded True  64   -> "SInt64"
+                        k@KBounded{}        -> error $ "SBV.renderTest: Unsupported kind: " ++ show k
                         KFloat              -> "SFloat"
                         KDouble             -> "SDouble"
                         KChar               -> error "SBV.renderTest: Unsupported char"
@@ -226,8 +233,13 @@
                         KUnbounded          -> error "SBV.renderTest: Unbounded integers are not supported when generating C test-cases."
                         KReal               -> error "SBV.renderTest: Real values are not supported when generating C test-cases."
                         KUninterpreted us _ -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
-                        _                   -> error $ "SBV.renderTest: Unexpected CV: " ++ show cv
+                        k@KList{}           -> error $ "SBV.renderTest: Unsupported list sort: "   ++ show k
+                        k@KSet{}            -> error $ "SBV.renderTest: Unsupported set sort: "   ++ show k
+                        k@KTuple{}          -> error $ "SBV.renderTest: Unsupported tuple sort: "  ++ show k
+                        k@KMaybe{}          -> error $ "SBV.renderTest: Unsupported maybe sort: "  ++ show k
+                        k@KEither{}         -> error $ "SBV.renderTest: Unsupported either sort: " ++ show k
 
+
         mkLine (is, os) = "{{" ++ intercalate ", " (map v is) ++ "}, {" ++ intercalate ", " (map v os) ++ "}}"
 
         v cv = case kindOf cv of
@@ -239,9 +251,12 @@
                   KChar               -> error "SBV.renderTest: Unsupported char"
                   KString             -> error "SBV.renderTest: Unsupported string"
                   k@KList{}           -> error $ "SBV.renderTest: Unsupported list sort!" ++ show k
+                  k@KSet{}            -> error $ "SBV.renderTest: Unsupported set sort!" ++ show k
                   KUninterpreted us _ -> error $ "SBV.renderTest: Unsupported uninterpreted sort: " ++ us
                   KReal               -> error "SBV.renderTest: Real values are not supported when generating C test-cases."
                   k@KTuple{}          -> error $ "SBV.renderTest: Unsupported tuple sort!" ++ show k
+                  k@KMaybe{}          -> error $ "SBV.renderTest: Unsupported maybe sort!" ++ show k
+                  k@KEither{}         -> error $ "SBV.renderTest: Unsupported sum sort!" ++ show k
 
         outLine
           | null vs = "printf(\"\");"
@@ -307,6 +322,7 @@
                         KString            -> noForte "String"
                         KReal              -> noForte "Real"
                         KList ek           -> noForte $ "List of " ++ show ek
+                        KSet  ek           -> noForte $ "Set of " ++ show ek
                         KUnbounded         -> noForte "Unbounded integers"
                         KUninterpreted s _ -> noForte $ "Uninterpreted kind " ++ show s
                         _                  -> error $ "SBV.renderTest: Unexpected CV: " ++ show cv
@@ -318,7 +334,10 @@
         xlt _ (CString   r)  = error $ "SBV.renderTest.Forte: Unexpected string value: "        ++ show r
         xlt _ (CAlgReal  r)  = error $ "SBV.renderTest.Forte: Unexpected real value: "          ++ show r
         xlt _ CList{}        = error   "SBV.renderTest.Forte: Unexpected list value!"
+        xlt _ CSet{}         = error   "SBV.renderTest.Forte: Unexpected set value!"
         xlt _ CTuple{}       = error   "SBV.renderTest.Forte: Unexpected list value!"
+        xlt _ CMaybe{}       = error   "SBV.renderTest.Forte: Unexpected maybe value!"
+        xlt _ CEither{}      = error   "SBV.renderTest.Forte: Unexpected sum value!"
         xlt _ (CUserSort r)  = error $ "SBV.renderTest.Forte: Unexpected uninterpreted value: " ++ show r
 
         mkLine  (i, o) = "("  ++ mkTuple (form (fst ss) (concatMap blast i)) ++ ", " ++ mkTuple (form (snd ss) (concatMap blast o)) ++ ")"
diff --git a/Data/SBV/Tools/Induction.hs b/Data/SBV/Tools/Induction.hs
--- a/Data/SBV/Tools/Induction.hs
+++ b/Data/SBV/Tools/Induction.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.Induction
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -124,7 +124,7 @@
 
         check p = runSMTWith cfg $ do
                         setup
-                        query $ do st <- fresh
+                        query $ do st <- create
                                    constrain $ sNot (p st)
 
                                    cs <- checkSat
@@ -132,7 +132,7 @@
                                      Unk   -> error "Solver said unknown"
                                      Unsat -> return Nothing
                                      Sat   -> do io $ msg "Failed:"
-                                                 ex <- extract st
+                                                 ex <- project st
                                                  io $ msg $ show ex
                                                  return $ Just ex
 
diff --git a/Data/SBV/Tools/Overflow.hs b/Data/SBV/Tools/Overflow.hs
--- a/Data/SBV/Tools/Overflow.hs
+++ b/Data/SBV/Tools/Overflow.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.Overflow
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -10,13 +10,12 @@
 -- Based on: <http://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/z3prefix.pdf>
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE ImplicitParams       #-}
-{-# LANGUAGE Rank2Types           #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeApplications     #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ImplicitParams      #-}
+{-# LANGUAGE Rank2Types          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
 
 module Data.SBV.Tools.Overflow (
 
diff --git a/Data/SBV/Tools/Polynomial.hs b/Data/SBV/Tools/Polynomial.hs
--- a/Data/SBV/Tools/Polynomial.hs
+++ b/Data/SBV/Tools/Polynomial.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.Polynomial
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,10 +9,9 @@
 -- Implementation of polynomial arithmetic
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE PatternGuards        #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE PatternGuards     #-}
 
 module Data.SBV.Tools.Polynomial (
         -- * Polynomial arithmetic and CRCs
diff --git a/Data/SBV/Tools/Range.hs b/Data/SBV/Tools/Range.hs
--- a/Data/SBV/Tools/Range.hs
+++ b/Data/SBV/Tools/Range.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.Range
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -85,11 +85,11 @@
 -- [(0.0,oo)]
 -- >>> ranges $ \x -> x .< (0::SReal)
 -- [(-oo,0.0)]
-ranges :: forall a. (Num a, SymVal a,  SMTValue a, SatModel a, Metric (SBV a)) => (SBV a -> SBool) -> IO [Range a]
+ranges :: forall a. (Ord a, Num a, SymVal a,  SMTValue a, SatModel a, Metric a, SymVal (MetricSpace a), SatModel (MetricSpace a)) => (SBV a -> SBool) -> IO [Range a]
 ranges = rangesWith defaultSMTCfg
 
 -- | Compute ranges, using the given solver configuration.
-rangesWith :: forall a. (Num a, SymVal a,  SMTValue a, SatModel a, Metric (SBV a)) => SMTConfig -> (SBV a -> SBool) -> IO [Range a]
+rangesWith :: forall a. (Ord a, Num a, SymVal a,  SMTValue a, SatModel a, Metric a, SymVal (MetricSpace a), SatModel (MetricSpace a)) => SMTConfig -> (SBV a -> SBool) -> IO [Range a]
 rangesWith cfg prop = do mbBounds <- getInitialBounds
                          case mbBounds of
                            Nothing -> return []
@@ -128,8 +128,10 @@
 
                 getRegVal :: CV -> a
                 getRegVal cv = case parseCVs [cv] of
-                                 Just (v, []) -> v
-                                 _            -> error $ "Data.SBV.interval.getRegVal: Cannot parse " ++ show cv
+                                 Just (v :: MetricSpace a, []) -> case unliteral (fromMetricSpace (literal v)) of
+                                                                    Nothing -> error $ "Data.SBV.ranges.getRegVal: Cannot extract value from metric space equivalent: " ++ show cv
+                                                                    Just r  -> r
+                                 _                             -> error $ "Data.SBV.ranges.getRegVal: Cannot parse " ++ show cv
 
             IndependentResult m <- optimizeWith cfg Independent $ do x <- free_
                                                                      constrain $ prop x
@@ -171,3 +173,5 @@
                                  case mbCS of
                                    Nothing  -> search cs          (c:sofar)
                                    Just xss -> search (xss ++ cs) sofar
+
+{-# ANN rangesWith ("HLint: ignore Use fromMaybe" :: String) #-}
diff --git a/Data/SBV/Tools/STree.hs b/Data/SBV/Tools/STree.hs
--- a/Data/SBV/Tools/STree.hs
+++ b/Data/SBV/Tools/STree.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tools.STree
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -10,11 +10,10 @@
 -- time access to elements. Both reads and writes are supported.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleContexts     #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeApplications     #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
 
 module Data.SBV.Tools.STree (STree, readSTree, writeSTree, mkSTree) where
 
diff --git a/Data/SBV/Tools/WeakestPreconditions.hs b/Data/SBV/Tools/WeakestPreconditions.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Tools/WeakestPreconditions.hs
@@ -0,0 +1,485 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Data.SBV.Tools.WeakestPreconditions
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- A toy imperative language with a proof system based on Dijkstra's weakest
+-- preconditions methodology to establish partial/total correctness proofs.
+--
+-- See @Documentation.SBV.Examples.WeakestPreconditions@ directory for
+-- several example proofs.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE FlexibleContexts       #-}
+{-# LANGUAGE MultiParamTypeClasses  #-}
+{-# LANGUAGE NamedFieldPuns         #-}
+{-# LANGUAGE ScopedTypeVariables    #-}
+
+module Data.SBV.Tools.WeakestPreconditions (
+        -- * Programs and statements
+          Program(..), Stmt(..), assert, stable
+
+        -- * Invariants, measures, and stability
+        , Invariant, Measure, Stable
+
+        -- * Verification conditions
+        , VC(..)
+
+        -- * Result of a proof
+        , ProofResult(..)
+
+        -- * Configuring the WP engine
+        , WPConfig(..), defaultWPCfg
+
+        -- * Checking WP correctness
+        , wpProve, wpProveWith
+
+        -- * Concrete runs of programs
+        , traceExecution, Status(..)
+        ) where
+
+import Data.List   (intercalate)
+import Data.Maybe  (fromJust, isJust, isNothing)
+
+import Control.Monad (when)
+
+import Data.SBV
+import Data.SBV.Control
+
+-- | A program over a state is simply a statement, together with
+-- a pre-condition capturing environmental assumptions and
+-- a post-condition that states its correctness. In the usual
+-- Hoare-triple notation, it captures:
+--
+--   @ {precondition} program {postcondition} @
+--
+-- We also allow for a stability check, which is ensured at
+-- every assignment statement to deal with ghost variables.
+-- In general, this is useful for making sure what you consider
+-- as "primary inputs" remain unaffected. Of course, you can
+-- also put any arbitrary condition you want to check that you
+-- want performed for each 'Assign' statement.
+--
+-- Note that stability is quite a strong condition: It is intended
+-- to capture constants that never change during execution. So,
+-- if you have a program that changes an input temporarily but
+-- always restores it at the end, it would still fail the stability
+-- condition.
+--
+-- The 'setup' field is reserved for any symbolic code you might
+-- want to run before the proof takes place, typically for calls
+-- to 'Data.SBV.setOption'. If not needed, simply pass @return ()@.
+-- For an interesting use case where we use setup to axiomatize
+-- the spec, see "Documentation.SBV.Examples.WeakestPreconditions.Fib"
+-- and "Documentation.SBV.Examples.WeakestPreconditions.GCD".
+data Program st = Program { setup         :: Symbolic ()  -- ^ Any set-up required
+                          , precondition  :: st -> SBool  -- ^ Environmental assumptions
+                          , program       :: Stmt st      -- ^ Program
+                          , postcondition :: st -> SBool  -- ^ Correctness statement
+                          , stability     :: Stable st    -- ^ Each assignment must satisfy stability
+                          }
+
+-- | A stability condition captures a primary input that does not change. Use 'stable'
+-- to create elements of this type.
+type Stable st = [st -> st -> (String, SBool)]
+
+-- | An invariant takes a state and evaluates to a boolean.
+type Invariant st = st -> SBool
+
+-- | A measure takes the state and returns a sequence of integers. The ordering
+-- will be done lexicographically over the elements.
+type Measure st = st -> [SInteger]
+
+-- | A statement in our imperative program, parameterized over the state.
+data Stmt st = Skip                                                                     -- ^ Skip, do nothing.
+             | Abort String                                                             -- ^ Abort execution. The name is for diagnostic purposes.
+             | Assign (st -> st)                                                        -- ^ Assignment: Transform the state by a function.
+             | If (st -> SBool) (Stmt st) (Stmt st)                                     -- ^ Conditional: @If condition thenBranch elseBranch@.
+             | While String (Invariant st) (Maybe (Measure st)) (st -> SBool) (Stmt st) -- ^ A while loop: @While name invariant measure condition body@.
+                                                                                        -- The string @name@ is merely for diagnostic purposes.
+                                                                                        -- If the measure is 'Nothing', then only partial correctness
+                                                                                        -- of this loop will be proven.
+             | Seq [Stmt st]                                                            -- ^ A sequence of statements.
+
+-- | An 'assert' is a quick way of ensuring some condition holds. If it does,
+-- then it's equivalent to 'Skip'. Otherwise, it is equivalent to 'Abort'.
+assert :: String -> (st -> SBool) -> Stmt st
+assert nm cond = If cond Skip (Abort nm)
+
+-- | Stability: A call of the form @stable "f" f@ means the value of the field @f@
+-- does not change during any assignment. The string argument is for diagnostic
+-- purposes only. Note that we use strong-equality here, so if the program
+-- is manipulating floats, we don't get a false-positive on @NaN@ and also
+-- not miss @+0@ and @-@@ changes.
+stable :: EqSymbolic a => String -> (st -> a) -> st -> st -> (String, SBool)
+stable nm f before after = (nm, f before .=== f after)
+
+-- | Are all the termination measures provided?
+isTotal :: Stmt st -> Bool
+isTotal Skip                = True
+isTotal (Abort _)           = True
+isTotal (Assign _)          = True
+isTotal (If _ tb fb)        = all isTotal [tb, fb]
+isTotal (While _ _ msr _ s) = isJust msr && isTotal s
+isTotal (Seq ss)            = all isTotal ss
+
+-- | A verification condition. Upon failure, each 'VC' carries enough state and diagnostic information
+-- to indicate what particular proof obligation failed for further debugging.
+data VC st m = BadPrecondition          st                  -- ^ The precondition doesn't hold. This can only happen in 'traceExecution'.
+             | BadPostcondition         st st               -- ^ The postcondition doesn't hold
+             | Unstable          String st st               -- ^ Stability condition is violated
+             | AbortReachable    String st st               -- ^ The named abort condition is reachable
+             | InvariantPre      String st                  -- ^ Invariant doesn't hold upon entry to the named loop
+             | InvariantMaintain String st st               -- ^ Invariant isn't maintained by the body
+             | MeasureBound      String (st, [m])           -- ^ Measure cannot be shown to be non-negative
+             | MeasureDecrease   String (st, [m]) (st, [m]) -- ^ Measure cannot be shown to decrease through each iteration
+
+-- | Helper function to display VC's nicely
+dispVC :: String -> [(String, String)] -> String
+dispVC tag flds = intercalate "\n" $ col tag : map showField flds
+  where col "" = ""
+        col t  = t ++ ":"
+
+        showField (t, c) = intercalate "\n" $ zipWith mark [(1::Int)..] (lines c)
+           where tt   = if null t then "" else col t ++ " "
+                 sp   = replicate (length tt) ' '
+                 mark i s = "  " ++ (if i == 1 then tt else sp) ++ s
+
+-- If a measure is a singleton, just show the number. Otherwise as a list:
+showMeasure :: Show a => [a] -> String
+showMeasure [x] = show x
+showMeasure xs  = show xs
+
+-- | Show instance for VC's
+instance (Show st, Show m) => Show (VC st m) where
+  show (BadPrecondition   s)                    = dispVC "Precondition fails"
+                                                         [("", show s)]
+  show (BadPostcondition  s1 s2)                = dispVC "Postcondition fails"
+                                                         [ ("Start", show s1)
+                                                         , ("End  ", show s2)
+                                                         ]
+  show (Unstable          m s1 s2)              = dispVC ("Stability fails for " ++ show m)
+                                                         [ ("Before", show s1)
+                                                         , ("After ", show s2)
+                                                         ]
+  show (AbortReachable    nm s1 s2)             = dispVC ("Abort " ++ show nm ++ " condition is satisfiable")
+                                                         [ ("Before", show s1)
+                                                         , ("After ", show s2)
+                                                         ]
+  show (InvariantPre      nm s)                 = dispVC ("Invariant for loop " ++ show nm ++ " fails upon entry")
+                                                         [("", show s)]
+  show (InvariantMaintain nm s1 s2)             = dispVC ("Invariant for loop " ++ show nm ++ " is not maintaned by the body")
+                                                         [ ("Before", show s1)
+                                                         , ("After ", show s2)
+                                                         ]
+  show (MeasureBound      nm (s, m))            = dispVC ("Measure for loop "   ++ show nm ++ " is negative")
+                                                         [ ("State  ", show s)
+                                                         , ("Measure", showMeasure m )
+                                                         ]
+  show (MeasureDecrease   nm (s1, m1) (s2, m2)) = dispVC ("Measure for loop "   ++ show nm ++ " does not decrease")
+                                                         [ ("Before ", show s1)
+                                                         , ("Measure", showMeasure m1)
+                                                         , ("After  ", show s2)
+                                                         , ("Measure", showMeasure m2)
+                                                         ]
+
+-- | The result of a weakest-precondition proof.
+data ProofResult res = Proven Bool                -- ^ The property holds. If 'Bool' is 'True', then total correctness, otherwise partial.
+                     | Indeterminate String       -- ^ Failed to establish correctness. Happens when the proof obligations lead to
+                                                  -- the SMT solver to return @Unk@. This can happen, for instance, if you have
+                                                  -- non-linear constraints, causing the solver to give up.
+                     | Failed [VC res Integer]    -- ^ The property fails, failing to establish the conditions listed.
+
+-- | 'Show' instance for proofs, for readability.
+instance Show res => Show (ProofResult res) where
+  show (Proven True)     = "Q.E.D."
+  show (Proven False)    = "Q.E.D. [Partial: not all termination measures were provided.]"
+  show (Indeterminate s) = "Indeterminate: " ++ s
+  show (Failed vcs)      = intercalate "\n" $ ("Proof failure. Failing verification condition" ++ if length vcs > 1 then "s:" else ":")
+                                              : map (\vc -> intercalate "\n" ["  " ++ l | l <- lines (show vc)]) vcs
+
+
+
+-- | Checking WP based correctness
+wpProveWith :: forall st res. (Show res, Mergeable st, Queriable IO st res) => WPConfig -> Program st -> IO (ProofResult res)
+wpProveWith cfg@WPConfig{wpVerbose} Program{setup, precondition, program, postcondition, stability} =
+   runSMTWith (wpSolver cfg) $ do setup
+                                  query q
+  where q = do start <- create
+
+               weakestPrecondition <- wp start program (\st -> [(postcondition st, BadPostcondition start st)])
+
+               let vcs = weakestPrecondition start
+
+               constrain $ sNot $ precondition start .=> sAnd (map fst vcs)
+
+               cs <- checkSat
+               case cs of
+                 Unk   -> Indeterminate . show <$> getUnknownReason
+
+                 Unsat -> do let t = isTotal program
+
+                             if t then msg "Total correctness is established."
+                                  else msg "Partial correctness is established."
+
+                             return $ Proven t
+
+                 Sat   -> do let checkVC :: (SBool, VC st SInteger) -> Query [VC res Integer]
+                                 checkVC (cond, vc) = do c <- getValue cond
+                                                         if c
+                                                            then return []   -- The VC was OK
+                                                            else do vc' <- case vc of
+                                                                             BadPrecondition     s                 -> BadPrecondition     <$> project s
+                                                                             BadPostcondition    s1 s2             -> BadPostcondition    <$> project s1 <*> project s2
+                                                                             Unstable          l s1 s2             -> Unstable          l <$> project s1 <*> project s2
+                                                                             AbortReachable    l s1 s2             -> AbortReachable    l <$> project s1 <*> project s2
+                                                                             InvariantPre      l s                 -> InvariantPre      l <$> project s
+                                                                             InvariantMaintain l s1 s2             -> InvariantMaintain l <$> project s1 <*> project s2
+                                                                             MeasureBound      l (s, m)            -> do r <- project s
+                                                                                                                         v <- mapM getValue m
+                                                                                                                         return $ MeasureBound l (r, v)
+                                                                             MeasureDecrease   l (s1, i1) (s2, i2) -> do r1 <- project s1
+                                                                                                                         v1 <- mapM getValue i1
+                                                                                                                         r2 <- project s2
+                                                                                                                         v2 <- mapM getValue i2
+                                                                                                                         return $ MeasureDecrease l (r1, v1) (r2, v2)
+                                                                    return [vc']
+
+                             badVCs <- concat <$> mapM checkVC vcs
+
+                             when (null badVCs) $ error "Data.SBV.proveWP: Impossible happened. Proof failed, but no failing VC found!"
+
+                             let plu w (_:_:_) = w ++ "s"
+                                 plu w _       = w
+
+                                 m = "Following proof " ++ plu "obligation" badVCs ++ " failed:"
+
+                             msg m
+                             msg $ replicate (length m) '='
+
+                             let disp c = mapM_ msg ["  " ++ l | l <- lines (show c)]
+                             mapM_ disp badVCs
+
+                             return $ Failed badVCs
+
+        msg = io . when wpVerbose . putStrLn
+
+        -- Compute the weakest precondition to establish the property:
+        wp :: st -> Stmt st -> (st -> [(SBool, VC st SInteger)]) -> Query (st -> [(SBool, VC st SInteger)])
+
+        -- Skip simply keeps the conditions
+        wp _ Skip post = return post
+
+        -- Abort is never satisfiable. The only way to have Abort's VC to pass is
+        -- to run it in a precondition (either via program or in an if branch) that
+        -- evaluates to false, i.e., it must not be reachable.
+        wp start (Abort nm) _ = return $ \st -> [(sFalse, AbortReachable nm start st)]
+
+        -- Assign simply transforms the state and passes on. It also checks that the
+        -- stability constraints are not violated.
+        wp _ (Assign f) post = return $ \st -> let st'       = f st
+                                                   vcs       = map (\s -> let (nm, b) = s st st' in (b, Unstable nm st st')) stability
+                                               in vcs ++ post st'
+
+        -- Conditional: We separately collect the VCs, and predicate with the proper branch condition
+        wp start (If c tb fb) post = do tWP <- wp start tb post
+                                        fWP <- wp start fb post
+                                        return $ \st -> let cond = c st
+                                                        in   [(     cond .=> b, v) | (b, v) <- tWP st]
+                                                          ++ [(sNot cond .=> b, v) | (b, v) <- fWP st]
+
+        -- Sequencing: Simply run through the statements
+        wp _     (Seq [])              post = return post
+        wp start (Seq (s:ss))          post = wp start s =<< wp start (Seq ss) post
+
+        -- While loop, where all the WP magic happens!
+        wp start (While nm inv mm cond body) post = do
+                st'  <- create
+
+                let noMeasure = isNothing mm
+                    m         = fromJust mm
+                    curM      = m st'
+                    zero      = map (const 0) curM
+
+                    iterates   = inv st' .&&       cond st'
+                    terminates = inv st' .&& sNot (cond st')
+
+
+                -- Condition 1: Invariant must hold prior to loop entry
+                invHoldsPrior <- wp start Skip (\st -> [(inv st, InvariantPre nm st)])
+
+                -- Condition 2: If we iterate, invariant must be maitained by the body
+                invMaintained <- wp st' body (\st -> [(iterates .=> inv st, InvariantMaintain nm st' st)])
+
+                -- Condition 3: If we terminate, invariant must be strong enough to establish the post condition
+                invEstablish <- wp st' body (const [(terminates .=> b, v) | (b, v) <- post st'])
+
+                -- Condition 4: If we iterate, measure must always be non-negative
+                measureNonNegative <- if noMeasure
+                                      then return  (const [])
+                                      else wp st' Skip (const [(iterates .=> curM .>= zero, MeasureBound nm (st', curM))])
+
+                -- Condition 5: If we iterate, the measure must decrease
+                measureDecreases <- if noMeasure
+                                    then return  (const [])
+                                    else wp st' body (\st -> let prevM = m st in [(iterates .=> prevM .< curM, MeasureDecrease nm (st', curM) (st, prevM))])
+
+                -- Simply concatenate the VCs from all our conditions:
+                return $ \st ->    invHoldsPrior      st
+                                ++ invMaintained      st'
+                                ++ invEstablish       st'
+                                ++ measureNonNegative st'
+                                ++ measureDecreases   st'
+
+-- | Check correctness using the default solver. Equivalent to @'wpProveWith' 'defaultWPCfg'@.
+wpProve :: (Show res, Mergeable st, Queriable IO st res) => Program st -> IO (ProofResult res)
+wpProve = wpProveWith defaultWPCfg
+
+-- | Configuration for WP proofs.
+data WPConfig = WPConfig { wpSolver  :: SMTConfig   -- ^ SMT Solver to use
+                         , wpVerbose :: Bool        -- ^ Should we be chatty?
+                         }
+
+-- | Default WP configuration: Uses the default solver, and is not verbose.
+defaultWPCfg :: WPConfig
+defaultWPCfg = WPConfig { wpSolver  = defaultSMTCfg
+                        , wpVerbose = False
+                        }
+
+-- * Concrete execution of a program
+
+-- | Tracking locations: Either a line (sequence) number, or an iteration count
+data Location = Line      Int
+              | Iteration Int
+
+-- | A 'Loc' is a nesting of locations. We store this in reverse order.
+type Loc = [Location]
+
+-- | Are we in a good state, or in a stuck state?
+data Status st = Good st               -- ^ Execution finished in the given state.
+               | Stuck (VC st Integer) -- ^ Execution got stuck, with the failing VC
+
+-- | Show instance for 'Status'
+instance Show st => Show (Status st) where
+  show (Good st)  = "Program terminated successfully. Final state:\n" ++ intercalate "\n" ["  " ++ l | l <- lines (show st)]
+  show (Stuck vc) = "Program is stuck.\n" ++ show vc
+
+-- | Trace the execution of a program, starting from a sufficiently concrete state. (Sufficiently here means that
+-- all parts of the state that is used uninitialized must have concrete values, i.e., essentially the inputs.
+-- You can leave the "temporary" variables initialized by the program before use undefined or even symbolic.)
+-- The return value will have a 'Good' state to indicate the program ended successfully, if that is the case. The
+-- result will be 'Stuck' if the program aborts without completing: This can happen either by executing an 'Abort'
+-- statement, or some invariant gets violated, or if a metric fails to go down through a loop body.
+traceExecution :: forall st. Show st
+               => Program st            -- ^ Program
+               -> st                    -- ^ Starting state. It must be fully concrete.
+               -> IO (Status st)
+traceExecution Program{precondition, program, postcondition, stability} start = do
+
+                status <- if unwrap [] "checking precondition" (precondition start)
+                          then go [Line 1] program =<< step [] start "*** Precondition holds, starting execution:"
+                          else giveUp start (BadPrecondition start) "*** Initial state does not satisfy the precondition:"
+
+                case status of
+                  s@Stuck{} -> return s
+                  Good end  -> if unwrap [] "checking postcondition" (postcondition end)
+                               then step [] end "*** Program successfully terminated, post condition holds of the final state:"
+                               else giveUp end (BadPostcondition start end) "*** Failed, final state does not satisfy the postcondition:"
+
+  where sLoc :: Loc -> String -> String
+        sLoc l m
+          | null l = m
+          | True   = "===> [" ++ intercalate "." (map sh (reverse l)) ++ "] " ++ m
+          where sh (Line  i)     = show i
+                sh (Iteration i) = "{" ++ show i ++ "}"
+
+        step :: Loc -> st -> String -> IO (Status st)
+        step l st m = do putStrLn $ sLoc l m
+                         printST st
+                         return $ Good st
+
+        stop :: Loc -> VC st Integer -> String -> IO (Status st)
+        stop l vc m = do putStrLn $ sLoc l m
+                         return $ Stuck vc
+
+        giveUp :: st -> VC st Integer -> String -> IO (Status st)
+        giveUp st vc m = do r <- stop [] vc m
+                            printST st
+                            return r
+
+        dispST :: st -> String
+        dispST st = intercalate "\n" ["  " ++ l | l <- lines (show st)]
+
+        printST :: st -> IO ()
+        printST = putStrLn . dispST
+
+        unwrap :: SymVal a => Loc -> String -> SBV a -> a
+        unwrap l m v = case unliteral v of
+                         Just c  -> c
+                         Nothing -> error $ unlines [ ""
+                                                    , "*** Data.SBV.WeakestPreconditions.traceExecution:"
+                                                    , "***"
+                                                    , "***    Unable to extract concrete value:"
+                                                    , "***      "  ++ sLoc l m
+                                                    , "***"
+                                                    , "*** Make sure the starting state is fully concrete and"
+                                                    , "*** there are no uninterpreted functions in play!"
+                                                    ]
+
+        go :: Loc -> Stmt st -> Status st -> IO (Status st)
+        go _   _ s@Stuck{}  = return s
+        go loc p (Good  st) = analyze p
+          where analyze Skip = step loc st "Skip"
+
+                analyze (Abort nm) = stop loc (AbortReachable nm start st) $ "Abort command executed, labeled: " ++ show nm
+
+                analyze (Assign f) = case [nm | s <- stability, let (nm, b) = s st st', not (unwrap loc ("evaluation stability condition " ++ show nm) b)] of
+                                       []  -> step loc st' "Assign"
+                                       nms -> let comb = intercalate ", " nms
+                                                  bad  = Unstable comb st st'
+                                              in stop loc bad $ "Stability condition fails for: " ++ show comb
+                    where st' = f st
+
+                analyze (If c tb eb)
+                  | branchTrue       = go (Line 1 : loc) tb =<< step loc st "Conditional, taking the \"then\" branch"
+                  | True             = go (Line 2 : loc) eb =<< step loc st "Conditional, taking the \"else\" branch"
+                  where branchTrue = unwrap loc "evaluating the test condition" (c st)
+
+                analyze (Seq stmts)  = walk stmts 1 (Good st)
+                  where walk []     _ is = return is
+                        walk (s:ss) c is = walk ss (c+1) =<< go (Line c : loc) s is
+
+                analyze (While loopName invariant mbMeasure condition body)
+                   | currentInvariant st
+                   = while 1 st Nothing (Good st)
+                   | True
+                   = stop loc  (InvariantPre loopName st) $ tag "invariant fails to hold prior to loop entry"
+                   where tag s = "Loop " ++ show loopName ++ ": " ++ s
+
+                         hasMeasure = isJust mbMeasure
+                         measure    = fromJust mbMeasure
+
+                         currentCondition = unwrap loc (tag  "evaluating the while condition") . condition
+                         currentMeasure   = map (unwrap loc (tag  "evaluating the measure"))   . measure
+                         currentInvariant = unwrap loc (tag  "evaluating the invariant")       . invariant
+
+                         while _ _      _      s@Stuck{}  = return s
+                         while c prevST mbPrev (Good  is)
+                           | not (currentCondition is)
+                           = step loc is $ tag "condition fails, terminating"
+                           | not (currentInvariant is)
+                           = stop loc (InvariantMaintain loopName prevST is) $ tag "invariant fails to hold in iteration " ++ show c
+                           | hasMeasure && mCur < zero
+                           = stop loc (MeasureBound loopName (is, mCur)) $ tag "measure must be non-negative, evaluated to: " ++ show mCur
+                           | hasMeasure, Just mPrev <- mbPrev, mCur >= mPrev
+                           = stop loc (MeasureDecrease loopName (prevST, mPrev) (is, mCur)) $ tag $ "measure failed to decrease, prev = " ++ show mPrev ++ ", current = " ++ show mCur
+                           | True
+                           = do nextState <- go (Iteration c : loc) body =<< step loc is (tag "condition holds, executing the body")
+                                while (c+1) is (Just mCur) nextState
+                           where mCur = currentMeasure is
+                                 zero = map (const 0) mCur
+
+{-# ANN traceExecution ("HLint: ignore Use fromMaybe" :: String) #-}
diff --git a/Data/SBV/Trans.hs b/Data/SBV/Trans.hs
--- a/Data/SBV/Trans.hs
+++ b/Data/SBV/Trans.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Trans
--- Author    : Brian Schroeder, Levent Erkok
+-- Copyright : (c) Brian Schroeder
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -56,7 +57,7 @@
   -- ** Conversions
   , sFromIntegral
   -- ** Shifts and rotates
-  , sShiftLeft, sShiftRight, sRotateLeft, sRotateRight, sSignedShiftArithRight
+  , sShiftLeft, sShiftRight, sRotateLeft, sBarrelRotateLeft, sRotateRight, sBarrelRotateRight, sSignedShiftArithRight
   -- ** Finite bit-vector operations
   , SFiniteBits(..)
   -- ** Splitting, joining, and extending
@@ -68,7 +69,7 @@
   -- ** Rounding modes
   , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero, sRNE, sRNA, sRTP, sRTN, sRTZ
   -- ** Conversion to/from floats
-  , IEEEFloatConvertable(..)
+  , IEEEFloatConvertible(..)
   -- ** Bit-pattern conversions
   , sFloatAsSWord32, sWord32AsSFloat, sDoubleAsSWord64, sWord64AsSDouble, blastSFloat, blastSDouble
 
diff --git a/Data/SBV/Trans/Control.hs b/Data/SBV/Trans/Control.hs
--- a/Data/SBV/Trans/Control.hs
+++ b/Data/SBV/Trans/Control.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Trans.Control
--- Author    : Brian Schroeder, Levent Erkok
+-- Copyright : (c) Brian Schroeder
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -25,7 +26,7 @@
 
      -- * Querying the solver
      -- ** Extracting values
-     , SMTValue(..), getValue, getUninterpretedValue, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
+     , SMTValue(..), getValue, getFunction, getUninterpretedValue, getModel, getAssignment, getSMTResult, getUnknownReason, getObservables
 
      -- ** Extracting the unsat core
      , getUnsatCore
@@ -75,7 +76,7 @@
 import Data.SBV.Core.Symbolic (MonadQuery(..), QueryT, Query, SymbolicT, QueryContext(..))
 
 import Data.SBV.Control.Query
-import Data.SBV.Control.Utils (SMTValue(..), queryDebug, executeQuery)
+import Data.SBV.Control.Utils (SMTValue(..), queryDebug, executeQuery, getFunction)
 
 import Data.SBV.Utils.ExtractIO
 
diff --git a/Data/SBV/Tuple.hs b/Data/SBV/Tuple.hs
--- a/Data/SBV/Tuple.hs
+++ b/Data/SBV/Tuple.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Tuple
--- Author    : Joel Burget, Levent Erkok
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -14,11 +15,12 @@
 {-# LANGUAGE FlexibleInstances      #-}
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE KindSignatures         #-}
-{-# LANGUAGE MultiParamTypeClasses  #-}
 {-# LANGUAGE Rank2Types             #-}
 {-# LANGUAGE ScopedTypeVariables    #-}
 {-# LANGUAGE TypeApplications       #-}
 
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
 module Data.SBV.Tuple (
   -- * Symbolic field access
     (^.), _1, _2, _3, _4, _5, _6, _7, _8
@@ -30,7 +32,7 @@
 
 import Data.SBV.Core.Data
 import Data.SBV.Core.Symbolic
-import Data.SBV.Core.Model () -- instances only
+import Data.SBV.Core.Model
 
 -- For doctest use only
 --
@@ -193,7 +195,8 @@
                       bsv <- sbvToSV st sb
                       newExpr st k (SBVApp (TupleConstructor 2) [asv, bsv])
 
-instance (SymVal a, SymVal b, SymVal c) => Tuple (a, b, c) (SBV a, SBV b, SBV c) where
+instance (SymVal a, SymVal b, SymVal c)
+      => Tuple (a, b, c) (SBV a, SBV b, SBV c) where
   untuple p = (p^._1, p^._2, p^._3)
 
   tuple p@(sa, sb, sc)
@@ -207,7 +210,8 @@
                       csv <- sbvToSV st sc
                       newExpr st k (SBVApp (TupleConstructor 3) [asv, bsv, csv])
 
-instance (SymVal a, SymVal b, SymVal c, SymVal d) => Tuple (a, b, c, d) (SBV a, SBV b, SBV c, SBV d) where
+instance (SymVal a, SymVal b, SymVal c, SymVal d)
+      => Tuple (a, b, c, d) (SBV a, SBV b, SBV c, SBV d) where
   untuple p = (p^._1, p^._2, p^._3, p^._4)
 
   tuple p@(sa, sb, sc, sd)
@@ -222,7 +226,8 @@
                       dsv <- sbvToSV st sd
                       newExpr st k (SBVApp (TupleConstructor 4) [asv, bsv, csv, dsv])
 
-instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e) => Tuple (a, b, c, d, e) (SBV a, SBV b, SBV c, SBV d, SBV e) where
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e)
+      => Tuple (a, b, c, d, e) (SBV a, SBV b, SBV c, SBV d, SBV e) where
   untuple p = (p^._1, p^._2, p^._3, p^._4, p^._5)
 
   tuple p@(sa, sb, sc, sd, se)
@@ -238,7 +243,8 @@
                       esv <- sbvToSV st se
                       newExpr st k (SBVApp (TupleConstructor 5) [asv, bsv, csv, dsv, esv])
 
-instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f) => Tuple (a, b, c, d, e, f) (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) where
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f)
+      => Tuple (a, b, c, d, e, f) (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f) where
   untuple p = (p^._1, p^._2, p^._3, p^._4, p^._5, p^._6)
 
   tuple p@(sa, sb, sc, sd, se, sf)
@@ -255,7 +261,8 @@
                       fsv <- sbvToSV st sf
                       newExpr st k (SBVApp (TupleConstructor 6) [asv, bsv, csv, dsv, esv, fsv])
 
-instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g) => Tuple (a, b, c, d, e, f, g) (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) where
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g)
+      => Tuple (a, b, c, d, e, f, g) (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g) where
   untuple p = (p^._1, p^._2, p^._3, p^._4, p^._5, p^._6, p^._7)
 
   tuple p@(sa, sb, sc, sd, se, sf, sg)
@@ -273,7 +280,8 @@
                       gsv <- sbvToSV st sg
                       newExpr st k (SBVApp (TupleConstructor 7) [asv, bsv, csv, dsv, esv, fsv, gsv])
 
-instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h) => Tuple (a, b, c, d, e, f, g, h) (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h) where
+instance (SymVal a, SymVal b, SymVal c, SymVal d, SymVal e, SymVal f, SymVal g, SymVal h)
+      => Tuple (a, b, c, d, e, f, g, h) (SBV a, SBV b, SBV c, SBV d, SBV e, SBV f, SBV g, SBV h) where
   untuple p = (p^._1, p^._2, p^._3, p^._4, p^._5, p^._6, p^._7, p^._8)
 
   tuple p@(sa, sb, sc, sd, se, sf, sg, sh)
@@ -291,5 +299,133 @@
                       gsv <- sbvToSV st sg
                       hsv <- sbvToSV st sh
                       newExpr st k (SBVApp (TupleConstructor 8) [asv, bsv, csv, dsv, esv, fsv, gsv, hsv])
+
+-- Optimization for tuples
+
+-- 2-tuple
+instance ( SymVal a, Metric a
+         , SymVal b, Metric b)
+         => Metric (a, b) where
+   msMinimize nm p = do msMinimize (nm ++ "^._1") (p^._1)
+                        msMinimize (nm ++ "^._2") (p^._2)
+   msMaximize nm p = do msMaximize (nm ++ "^._1") (p^._1)
+                        msMaximize (nm ++ "^._2") (p^._2)
+
+-- 3-tuple
+instance ( SymVal a, Metric a
+         , SymVal b, Metric b
+         , SymVal c, Metric c)
+         => Metric (a, b, c) where
+   msMinimize nm p = do msMinimize (nm ++ "^._1") (p^._1)
+                        msMinimize (nm ++ "^._2") (p^._2)
+                        msMinimize (nm ++ "^._3") (p^._3)
+   msMaximize nm p = do msMaximize (nm ++ "^._1") (p^._1)
+                        msMaximize (nm ++ "^._2") (p^._2)
+                        msMaximize (nm ++ "^._3") (p^._3)
+
+-- 4-tuple
+instance ( SymVal a, Metric a
+         , SymVal b, Metric b
+         , SymVal c, Metric c
+         , SymVal d, Metric d)
+         => Metric (a, b, c, d) where
+   msMinimize nm p = do msMinimize (nm ++ "^._1") (p^._1)
+                        msMinimize (nm ++ "^._2") (p^._2)
+                        msMinimize (nm ++ "^._3") (p^._3)
+                        msMinimize (nm ++ "^._4") (p^._4)
+   msMaximize nm p = do msMaximize (nm ++ "^._1") (p^._1)
+                        msMaximize (nm ++ "^._2") (p^._2)
+                        msMaximize (nm ++ "^._3") (p^._3)
+                        msMaximize (nm ++ "^._4") (p^._4)
+
+-- 5-tuple
+instance ( SymVal a, Metric a
+         , SymVal b, Metric b
+         , SymVal c, Metric c
+         , SymVal d, Metric d
+         , SymVal e, Metric e)
+         => Metric (a, b, c, d, e) where
+   msMinimize nm p = do msMinimize (nm ++ "^._1") (p^._1)
+                        msMinimize (nm ++ "^._2") (p^._2)
+                        msMinimize (nm ++ "^._3") (p^._3)
+                        msMinimize (nm ++ "^._4") (p^._4)
+                        msMinimize (nm ++ "^._5") (p^._5)
+   msMaximize nm p = do msMaximize (nm ++ "^._1") (p^._1)
+                        msMaximize (nm ++ "^._2") (p^._2)
+                        msMaximize (nm ++ "^._3") (p^._3)
+                        msMaximize (nm ++ "^._4") (p^._4)
+                        msMaximize (nm ++ "^._5") (p^._5)
+
+-- 6-tuple
+instance ( SymVal a, Metric a
+         , SymVal b, Metric b
+         , SymVal c, Metric c
+         , SymVal d, Metric d
+         , SymVal e, Metric e
+         , SymVal f, Metric f)
+         => Metric (a, b, c, d, e, f) where
+   msMinimize nm p = do msMinimize (nm ++ "^._1") (p^._1)
+                        msMinimize (nm ++ "^._2") (p^._2)
+                        msMinimize (nm ++ "^._3") (p^._3)
+                        msMinimize (nm ++ "^._4") (p^._4)
+                        msMinimize (nm ++ "^._5") (p^._5)
+                        msMinimize (nm ++ "^._6") (p^._6)
+   msMaximize nm p = do msMaximize (nm ++ "^._1") (p^._1)
+                        msMaximize (nm ++ "^._2") (p^._2)
+                        msMaximize (nm ++ "^._3") (p^._3)
+                        msMaximize (nm ++ "^._4") (p^._4)
+                        msMaximize (nm ++ "^._5") (p^._5)
+                        msMaximize (nm ++ "^._6") (p^._6)
+
+-- 7-tuple
+instance ( SymVal a, Metric a
+         , SymVal b, Metric b
+         , SymVal c, Metric c
+         , SymVal d, Metric d
+         , SymVal e, Metric e
+         , SymVal f, Metric f
+         , SymVal g, Metric g)
+         => Metric (a, b, c, d, e, f, g) where
+   msMinimize nm p = do msMinimize (nm ++ "^._1") (p^._1)
+                        msMinimize (nm ++ "^._2") (p^._2)
+                        msMinimize (nm ++ "^._3") (p^._3)
+                        msMinimize (nm ++ "^._4") (p^._4)
+                        msMinimize (nm ++ "^._5") (p^._5)
+                        msMinimize (nm ++ "^._6") (p^._6)
+                        msMinimize (nm ++ "^._7") (p^._7)
+   msMaximize nm p = do msMaximize (nm ++ "^._1") (p^._1)
+                        msMaximize (nm ++ "^._2") (p^._2)
+                        msMaximize (nm ++ "^._3") (p^._3)
+                        msMaximize (nm ++ "^._4") (p^._4)
+                        msMaximize (nm ++ "^._5") (p^._5)
+                        msMaximize (nm ++ "^._6") (p^._6)
+                        msMaximize (nm ++ "^._7") (p^._7)
+
+-- 8-tuple
+instance ( SymVal a, Metric a
+         , SymVal b, Metric b
+         , SymVal c, Metric c
+         , SymVal d, Metric d
+         , SymVal e, Metric e
+         , SymVal f, Metric f
+         , SymVal g, Metric g
+         , SymVal h, Metric h)
+         => Metric (a, b, c, d, e, f, g, h) where
+   msMinimize nm p = do msMinimize (nm ++ "^._1") (p^._1)
+                        msMinimize (nm ++ "^._2") (p^._2)
+                        msMinimize (nm ++ "^._3") (p^._3)
+                        msMinimize (nm ++ "^._4") (p^._4)
+                        msMinimize (nm ++ "^._5") (p^._5)
+                        msMinimize (nm ++ "^._6") (p^._6)
+                        msMinimize (nm ++ "^._7") (p^._7)
+                        msMinimize (nm ++ "^._8") (p^._8)
+   msMaximize nm p = do msMaximize (nm ++ "^._1") (p^._1)
+                        msMaximize (nm ++ "^._2") (p^._2)
+                        msMaximize (nm ++ "^._3") (p^._3)
+                        msMaximize (nm ++ "^._4") (p^._4)
+                        msMaximize (nm ++ "^._5") (p^._5)
+                        msMaximize (nm ++ "^._6") (p^._6)
+                        msMaximize (nm ++ "^._7") (p^._7)
+                        msMaximize (nm ++ "^._8") (p^._8)
 
 {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Data/SBV/Utils/ExtractIO.hs b/Data/SBV/Utils/ExtractIO.hs
--- a/Data/SBV/Utils/ExtractIO.hs
+++ b/Data/SBV/Utils/ExtractIO.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Utils.ExtractIO
--- Author    : Brian Schroeder
+-- Copyright : (c) Brian Schroeder
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/Utils/Lib.hs b/Data/SBV/Utils/Lib.hs
--- a/Data/SBV/Utils/Lib.hs
+++ b/Data/SBV/Utils/Lib.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Utils.Lib
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Data/SBV/Utils/Numeric.hs b/Data/SBV/Utils/Numeric.hs
--- a/Data/SBV/Utils/Numeric.hs
+++ b/Data/SBV/Utils/Numeric.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Utils.Numeric
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -10,18 +10,6 @@
 -----------------------------------------------------------------------------
 
 module Data.SBV.Utils.Numeric where
-
--- | A variant of round; except defaulting to 0 when fed NaN or Infinity
-fpRound0 :: (RealFloat a, Integral b) => a -> b
-fpRound0 x
- | isNaN x || isInfinite x = 0
- | True                    = round x
-
--- | A variant of toRational; except defaulting to 0 when fed NaN or Infinity
-fpRatio0 :: (RealFloat a) => a -> Rational
-fpRatio0 x
- | isNaN x || isInfinite x = 0
- | True                    = toRational x
 
 -- | The SMT-Lib (in particular Z3) implementation for min/max for floats does not agree with
 -- Haskell's; and also it does not agree with what the hardware does. Sigh.. See:
diff --git a/Data/SBV/Utils/PrettyNum.hs b/Data/SBV/Utils/PrettyNum.hs
--- a/Data/SBV/Utils/PrettyNum.hs
+++ b/Data/SBV/Utils/PrettyNum.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Utils.PrettyNum
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -9,9 +9,8 @@
 -- Number representations in hex/bin
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE ScopedTypeVariables  #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 
 module Data.SBV.Utils.PrettyNum (
         PrettyNum(..), readBin, shex, chex, shexI, sbin, sbinI
@@ -25,8 +24,12 @@
 import Data.Maybe (fromJust, fromMaybe, listToMaybe)
 import Data.Ratio (numerator, denominator)
 import Data.Word  (Word8, Word16, Word32, Word64)
-import Numeric    (showIntAtBase, showHex, readInt)
 
+import qualified Data.Set as Set
+
+import Numeric (showIntAtBase, showHex, readInt)
+import qualified Numeric (showHFloat)
+
 import Data.Numbers.CrackNum (floatToFP, doubleToFP)
 
 import Data.SBV.Core.Data
@@ -37,10 +40,14 @@
 
 -- | PrettyNum class captures printing of numbers in hex and binary formats; also supporting negative numbers.
 class PrettyNum a where
-  -- | Show a number in hexadecimal (starting with @0x@ and type.)
+  -- | Show a number in hexadecimal, starting with @0x@ and type.
   hexS :: a -> String
-  -- | Show a number in binary (starting with @0b@ and type.)
+  -- | Show a number in binary, starting with @0b@ and type.
   binS :: a -> String
+  -- | Show a number in hexadecimal, starting with @0x@ but no type.
+  hexP :: a -> String
+  -- | Show a number in binary, starting with @0b@ but no type.
+  binP :: a -> String
   -- | Show a number in hex, without prefix, or types.
   hex :: a -> String
   -- | Show a number in bin, without prefix, or types.
@@ -48,28 +55,111 @@
 
 -- Why not default methods? Because defaults need "Integral a" but Bool is not..
 instance PrettyNum Bool where
-  {hexS = show; binS = show; hex = show; bin = show}
+  hexS = show
+  binS = show
+  hexP = show
+  binP = show
+  hex  = show
+  bin  = show
+
 instance PrettyNum String where
-  {hexS = show; binS = show; hex = show; bin = show}
+  hexS = show
+  binS = show
+  hexP = show
+  binP = show
+  hex  = show
+  bin  = show
+
 instance PrettyNum Word8 where
-  {hexS = shex True True (False,8) ; binS = sbin True True (False,8) ; hex = shex False False (False,8) ; bin = sbin False False (False,8) ;}
+  hexS = shex True  True  (False, 8)
+  binS = sbin True  True  (False, 8)
+
+  hexP = shex False True  (False, 8)
+  binP = sbin False True  (False, 8)
+
+  hex  = shex False False (False, 8)
+  bin  = sbin False False (False, 8)
+
 instance PrettyNum Int8 where
-  {hexS = shex True True (True,8)  ; binS = sbin True True (True,8)  ; hex = shex False False (True,8)  ; bin = sbin False False (True,8)  ;}
+  hexS = shex True  True  (True, 8)
+  binS = sbin True  True  (True, 8)
+
+  hexP = shex False True  (True, 8)
+  binP = sbin False True  (True, 8)
+
+  hex  = shex False False (True, 8)
+  bin  = sbin False False (True, 8)
+
 instance PrettyNum Word16 where
-  {hexS = shex True True (False,16); binS = sbin True True (False,16); hex = shex False False (False,16); bin = sbin False False (False,16);}
-instance PrettyNum Int16  where
-  {hexS = shex True True (True,16);  binS = sbin True True (True,16) ; hex = shex False False (True,16);  bin = sbin False False (True,16) ;}
+  hexS = shex True  True  (False, 16)
+  binS = sbin True  True  (False, 16)
+
+  hexP = shex False True  (False, 16)
+  binP = sbin False True  (False, 16)
+
+  hex  = shex False False (False, 16)
+  bin  = sbin False False (False, 16)
+
+instance PrettyNum Int16 where
+  hexS = shex True  True  (True, 16)
+  binS = sbin True  True  (True, 16)
+
+  hexP = shex False True  (True, 16)
+  binP = sbin False True  (True, 16)
+
+  hex  = shex False False (True, 16)
+  bin  = sbin False False (True, 16)
+
 instance PrettyNum Word32 where
-  {hexS = shex True True (False,32); binS = sbin True True (False,32); hex = shex False False (False,32); bin = sbin False False (False,32);}
-instance PrettyNum Int32  where
-  {hexS = shex True True (True,32);  binS = sbin True True (True,32) ; hex = shex False False (True,32);  bin = sbin False False (True,32) ;}
+  hexS = shex True  True  (False, 32)
+  binS = sbin True  True  (False, 32)
+
+  hexP = shex False True  (False, 32)
+  binP = sbin False True  (False, 32)
+
+  hex  = shex False False (False, 32)
+  bin  = sbin False False (False, 32)
+
+instance PrettyNum Int32 where
+  hexS = shex True  True  (True, 32)
+  binS = sbin True  True  (True, 32)
+
+  hexP = shex False True  (True, 32)
+  binP = sbin False True  (True, 32)
+
+  hex  = shex False False (True, 32)
+  bin  = sbin False False (True, 32)
+
 instance PrettyNum Word64 where
-  {hexS = shex True True (False,64); binS = sbin True True (False,64); hex = shex False False (False,64); bin = sbin False False (False,64);}
-instance PrettyNum Int64  where
-  {hexS = shex True True (True,64);  binS = sbin True True (True,64) ; hex = shex False False (True,64);  bin = sbin False False (True,64) ;}
+  hexS = shex True  True  (False, 64)
+  binS = sbin True  True  (False, 64)
+
+  hexP = shex False True  (False, 64)
+  binP = sbin False True  (False, 64)
+
+  hex  = shex False False (False, 64)
+  bin  = sbin False False (False, 64)
+
+instance PrettyNum Int64 where
+  hexS = shex True  True  (True, 64)
+  binS = sbin True  True  (True, 64)
+
+  hexP = shex False True  (True, 64)
+  binP = sbin False True  (True, 64)
+
+  hex  = shex False False (True, 64)
+  bin  = sbin False False (True, 64)
+
 instance PrettyNum Integer where
-  {hexS = shexI True True; binS = sbinI True True; hex = shexI False False; bin = sbinI False False;}
+  hexS = shexI True  True
+  binS = sbinI True  True
 
+  hexP = shexI False True
+  binP = sbinI False True
+
+  hex  = shexI False False
+  bin  = sbinI False False
+
 instance PrettyNum CV where
   hexS cv | isUninterpreted cv = show cv ++ " :: " ++ show (kindOf cv)
           | isBoolean       cv = hexS (cvToBool cv) ++ " :: Bool"
@@ -89,8 +179,26 @@
           | not (isBounded cv) = let CInteger i = cvVal cv in sbinI True True i
           | True               = let CInteger i = cvVal cv in sbin  True True (hasSign cv, intSizeOf cv) i
 
+  hexP cv | isUninterpreted cv = show cv
+          | isBoolean       cv = hexS (cvToBool cv)
+          | isFloat         cv = let CFloat   f = cvVal cv in show f
+          | isDouble        cv = let CDouble  d = cvVal cv in show d
+          | isReal          cv = let CAlgReal r = cvVal cv in show r
+          | isString        cv = let CString  s = cvVal cv in show s
+          | not (isBounded cv) = let CInteger i = cvVal cv in shexI False True i
+          | True               = let CInteger i = cvVal cv in shex  False True (hasSign cv, intSizeOf cv) i
+
+  binP cv | isUninterpreted cv = show cv
+          | isBoolean       cv = binS (cvToBool cv)
+          | isFloat         cv = let CFloat   f = cvVal cv in show f
+          | isDouble        cv = let CDouble  d = cvVal cv in show d
+          | isReal          cv = let CAlgReal r = cvVal cv in show r
+          | isString        cv = let CString  s = cvVal cv in show s
+          | not (isBounded cv) = let CInteger i = cvVal cv in sbinI False True i
+          | True               = let CInteger i = cvVal cv in sbin  False True (hasSign cv, intSizeOf cv) i
+
   hex cv | isUninterpreted cv = show cv
-         | isBoolean       cv = hexS (cvToBool cv) ++ " :: Bool"
+         | isBoolean       cv = hexS (cvToBool cv)
          | isFloat         cv = let CFloat   f = cvVal cv in show f
          | isDouble        cv = let CDouble  d = cvVal cv in show d
          | isReal          cv = let CAlgReal r = cvVal cv in show r
@@ -99,7 +207,7 @@
          | True               = let CInteger i = cvVal cv in shex  False False (hasSign cv, intSizeOf cv) i
 
   bin cv | isUninterpreted cv = show cv
-         | isBoolean       cv = binS (cvToBool cv) ++ " :: Bool"
+         | isBoolean       cv = binS (cvToBool cv)
          | isFloat         cv = let CFloat   f = cvVal cv in show f
          | isDouble        cv = let CDouble  d = cvVal cv in show d
          | isReal          cv = let CAlgReal r = cvVal cv in show r
@@ -110,6 +218,10 @@
 instance (SymVal a, PrettyNum a) => PrettyNum (SBV a) where
   hexS s = maybe (show s) (hexS :: a -> String) $ unliteral s
   binS s = maybe (show s) (binS :: a -> String) $ unliteral s
+
+  hexP s = maybe (show s) (hexP :: a -> String) $ unliteral s
+  binP s = maybe (show s) (binP :: a -> String) $ unliteral s
+
   hex  s = maybe (show s) (hex  :: a -> String) $ unliteral s
   bin  s = maybe (show s) (bin  :: a -> String) $ unliteral s
 
@@ -223,15 +335,15 @@
    | isNaN f             = "((float) NAN)"
    | isInfinite f, f < 0 = "((float) (-INFINITY))"
    | isInfinite f        = "((float) INFINITY)"
-   | True                = show f ++ "F"
+   | True                = Numeric.showHFloat f $ "F /* " ++ show f ++ "F */"
 
 -- | A version of show for doubles that generates correct C literals for nan/infinite. NB. Requires "math.h" to be included.
 showCDouble :: Double -> String
-showCDouble f
-   | isNaN f             = "((double) NAN)"
-   | isInfinite f, f < 0 = "((double) (-INFINITY))"
-   | isInfinite f        = "((double) INFINITY)"
-   | True                = show f
+showCDouble d
+   | isNaN d             = "((double) NAN)"
+   | isInfinite d, d < 0 = "((double) (-INFINITY))"
+   | isInfinite d        = "((double) INFINITY)"
+   | True                = Numeric.showHFloat d " /* " ++ show d ++ " */"
 
 -- | A version of show for floats that generates correct Haskell literals for nan/infinite
 showHFloat :: Float -> String
@@ -308,7 +420,10 @@
   | isChar x         , CChar c          <- cvVal x = smtLibHex 8 (fromIntegral (ord c))
   | isString x       , CString s        <- cvVal x = '\"' : stringToQFS s ++ "\""
   | isList x         , CList xs         <- cvVal x = smtLibSeq (kindOf x) xs
+  | isSet x          , CSet s           <- cvVal x = smtLibSet (kindOf x) s
   | isTuple x        , CTuple xs        <- cvVal x = smtLibTup (kindOf x) xs
+  | isMaybe x        , CMaybe mc        <- cvVal x = smtLibMaybe  (kindOf x) mc
+  | isEither x       , CEither ec       <- cvVal x = smtLibEither (kindOf x) ec
 
   | True = error $ "SBV.cvtCV: Impossible happened: Kind/Value disagreement on: " ++ show (kindOf x, x)
   where roundModeConvert s = fromMaybe s (listToMaybe [smtRoundingMode m | m <- [minBound .. maxBound] :: [RoundingMode], show m == s])
@@ -333,10 +448,32 @@
                                   in mkSeq (mkUnit . cvToSMTLib rm . CV ek <$> xs)
         smtLibSeq k _ = error "SBV.cvToSMTLib: Impossible case (smtLibSeq), received kind: " ++ show k
 
+        smtLibSet :: Kind -> RCSet CVal -> String
+        smtLibSet k set = case set of
+                            RegularSet    rs -> Set.foldr' (modify "true")  (start "false") rs
+                            ComplementSet rs -> Set.foldr' (modify "false") (start "true")  rs
+          where ke = case k of
+                       KSet ek -> ek
+                       _       -> error $ "SBV.cvToSMTLib: Impossible case (smtLibSet), received kind: " ++ show k
+
+                start def = "((as const " ++ smtType k ++ ") " ++ def ++ ")"
+
+                modify how e s = "(store " ++ s ++ " " ++ cvToSMTLib rm (CV ke e) ++ " " ++ how ++ ")"
+
         smtLibTup :: Kind -> [CVal] -> String
-        smtLibTup (KTuple []) _  = "SBVTuple0"
+        smtLibTup (KTuple []) _  = "mkSBVTuple0"
         smtLibTup (KTuple ks) xs = "(mkSBVTuple" ++ show (length ks) ++ " " ++ unwords (zipWith (\ek e -> cvToSMTLib rm (CV ek e)) ks xs) ++ ")"
         smtLibTup k           _  = error $ "SBV.cvToSMTLib: Impossible case (smtLibTup), received kind: " ++ show k
+
+        smtLibMaybe :: Kind -> Maybe CVal -> String
+        smtLibMaybe (KMaybe k) Nothing   = "(as nothing_SBVMaybe " ++ smtType (KMaybe k) ++ ")"
+        smtLibMaybe (KMaybe k) (Just  c) = "(just_SBVMaybe " ++ cvToSMTLib rm (CV k c) ++ ")"
+        smtLibMaybe k          _         = error $ "SBV.cvToSMTLib: Impossible case (smtLibMaybe), received kind: " ++ show k
+
+        smtLibEither :: Kind -> Either CVal CVal -> String
+        smtLibEither (KEither  k _) (Left c)  = "(left_SBVEither "  ++ cvToSMTLib rm (CV k c) ++ ")"
+        smtLibEither (KEither  _ k) (Right c) = "(right_SBVEither " ++ cvToSMTLib rm (CV k c) ++ ")"
+        smtLibEither k              _         = error $ "SBV.cvToSMTLib: Impossible case (smtLibEither), received kind: " ++ show k
 
         -- anomaly at the 2's complement min value! Have to use binary notation here
         -- as there is no positive value we can provide to make the bvneg work.. (see above)
diff --git a/Data/SBV/Utils/SExpr.hs b/Data/SBV/Utils/SExpr.hs
--- a/Data/SBV/Utils/SExpr.hs
+++ b/Data/SBV/Utils/SExpr.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Utils.SExpr
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -11,18 +11,22 @@
 
 {-# LANGUAGE BangPatterns #-}
 
-module Data.SBV.Utils.SExpr (SExpr(..), parenDeficit, parseSExpr) where
+module Data.SBV.Utils.SExpr (SExpr(..), parenDeficit, parseSExpr, parseSExprFunction) where
 
-import Data.Bits  (setBit, testBit)
-import Data.Word  (Word32, Word64)
-import Data.Char  (isDigit, ord, isSpace)
-import Data.List  (isPrefixOf)
-import Data.Maybe (fromMaybe, listToMaybe)
+import Data.Bits   (setBit, testBit)
+import Data.Char   (isDigit, ord, isSpace)
+import Data.Either (partitionEithers)
+import Data.List   (isPrefixOf)
+import Data.Maybe  (fromMaybe, listToMaybe)
+import Data.Word   (Word32, Word64)
+
 import Numeric    (readInt, readDec, readHex, fromRat)
 
 import Data.SBV.Core.AlgReals
 import Data.SBV.Core.Data (nan, infinity, RoundingMode(..))
 
+import Data.SBV.Utils.Numeric (fpIsEqualObjectH)
+
 import Data.Numbers.CrackNum (wordToFloat, wordToDouble)
 
 -- | ADT S-Expression format, suitable for representing get-model output of SMT-Lib
@@ -236,3 +240,146 @@
                  , (["RTN", "roundTowardNegative"],    show RoundTowardNegative)
                  , (["RTZ", "roundTowardZero"],        show RoundTowardZero)
                  ]
+
+-- | Parse a function like value. These come in two flavors: Either in the form of
+-- a store-expression or a lambda-expression. So we handle both here.
+parseSExprFunction :: SExpr -> Maybe (Either String ([([SExpr], SExpr)], SExpr))
+parseSExprFunction e
+  | Just r <- parseLambdaExpression  e = Just (Right r)
+  | Just r <- parseStoreAssociations e = Just r
+  | True                               = Nothing         -- out-of luck. NB. This is where we would add support for other solvers!
+
+-- | Parse a lambda expression, most likely z3 specific. There's some guess work
+-- involved here regarding how z3 produces lambda-expressions; while we try to
+-- be flexible, this is certainly not a full fledged parser. But hopefully it'll
+-- cover everything z3 will throw at it.
+parseLambdaExpression :: SExpr -> Maybe ([([SExpr], SExpr)], SExpr)
+parseLambdaExpression funExpr = case funExpr of
+                                  EApp [ECon "lambda", EApp params, body] -> mapM getParam params >>= flip lambda body >>= chainAssigns
+                                  _                                       -> Nothing
+  where getParam (EApp [ECon v, _]) = Just v
+        getParam _                  = Nothing
+
+        lambda :: [String] -> SExpr -> Maybe [Either ([SExpr], SExpr) SExpr]
+        lambda params body = reverse <$> go [] body
+          where true  = ENum (1, Nothing)
+                false = ENum (0, Nothing)
+
+                go :: [Either ([SExpr], SExpr) SExpr] -> SExpr -> Maybe [Either ([SExpr], SExpr) SExpr]
+                go sofar (EApp [ECon "ite", selector, thenBranch, elseBranch])
+                  = do s  <- select selector
+                       tB <- go [] thenBranch
+                       case cond s tB of
+                          Just sv -> go (Left sv : sofar) elseBranch
+                          _       -> Nothing
+
+                -- z3 sometimes puts together a bunch of booleans as final expression,
+                -- see if we can catch that.
+                go sofar e
+                 | Just s <- select e
+                 = go (Left (s, true) : sofar) false
+
+                -- Otherwise, just treat it as an "unknown" arbitrary expression
+                -- as the default. It could be something arbitrary of course, but it's
+                -- too complicated to parse; and hopefully this is good enogh.
+                go sofar e = Just $ Right e : sofar
+
+                cond :: [SExpr] -> [Either ([SExpr], SExpr) SExpr] -> Maybe ([SExpr], SExpr)
+                cond s [Right v] = Just (s, v)
+                cond _ _         = Nothing
+
+                -- select takes the condition of an ite, and returns precisely what match is done to the parameters
+                select :: SExpr -> Maybe [SExpr]
+                select e
+                   | Just dict <- build e [] = mapM (`lookup` dict) params
+                   | True                    = Nothing
+                  where -- build a dictionary of assignments from the scrutinee
+                        build :: SExpr -> [(String, SExpr)] -> Maybe [(String, SExpr)]
+                        build (EApp (ECon "and" : rest)) sofar = let next _ Nothing  = Nothing
+                                                                     next c (Just x) = build c x
+                                                                 in foldr next (Just sofar) rest
+
+                        build expr sofar | Just (v, r) <- grok expr, v `elem` params = Just $ (v, r) : sofar
+                                         | True                                      = Nothing
+
+                        -- See if we can figure out what z3 is telling us; hopefully this
+                        -- mapping covers everything we can see:
+                        grok (EApp [ECon "=", ECon v, r]) = Just (v, r)
+                        grok (EApp [ECon "=", r, ECon v]) = Just (v, r)
+                        grok (EApp [ECon "not", ECon v])  = Just (v, false) -- boolean negation, require it to be false
+                        grok (ECon v)                     = Just (v, true)  -- boolean identity, require it to be true
+
+                        -- Tough luck, we couldn't understand:
+                        grok _ = Nothing
+
+-- | Parse a series of associations in the array notation, things that look like:
+--
+--     (store (store ((as const Array) 12) 3 5 9) 5 6 75)
+--
+-- This is (most likely) entirely Z3 specific. So, we might have to tweak it for other
+-- solvers; though it isn't entirely clear how to do that as we do not know what solver
+-- we're using here. The trick is to handle all of possible SExpr's we see.
+-- We'll cross that bridge when we get to it.
+--
+-- NB. In case there's no "constraint" on the UI, Z3 produces the self-referential model:
+--
+--    (x (_ as-array x))
+--
+-- So, we specifically handle that here, by returning a Left of that name.
+parseStoreAssociations :: SExpr -> Maybe (Either String ([([SExpr], SExpr)], SExpr))
+parseStoreAssociations (EApp [ECon "_", ECon "as-array", ECon nm]) = Just $ Left nm
+parseStoreAssociations e                                           = Right <$> (chainAssigns =<< vals e)
+    where vals :: SExpr -> Maybe [Either ([SExpr], SExpr) SExpr]
+          vals (EApp [EApp [ECon "as", ECon "const", ECon "Array"],            defVal]) = return [Right defVal]
+          vals (EApp [EApp [ECon "as", ECon "const", EApp (ECon "Array" : _)], defVal]) = return [Right defVal]
+          vals (EApp (ECon "store" : prev : argsVal)) | length argsVal >= 2             = do rest <- vals prev
+                                                                                             return $ Left (init argsVal, last argsVal) : rest
+          vals _                                                                        = Nothing
+
+-- | Turn a sequence of left-right chain assignments (condition + free) into a single chain
+chainAssigns :: [Either ([SExpr], SExpr) SExpr] -> Maybe ([([SExpr], SExpr)], SExpr)
+chainAssigns chain = regroup $ partitionEithers chain
+  where regroup (vs, [d]) = Just (checkDup vs, d)
+        regroup _         = Nothing
+
+        -- If we get into a case like this:
+        --
+        --     (store (store a 1 2) 1 3)
+        --
+        -- then we need to drop the 1->2 assignment!
+        --
+        -- The way we parse these, the first assignment wins.
+        checkDup :: [([SExpr], SExpr)] -> [([SExpr], SExpr)]
+        checkDup []              = []
+        checkDup (a@(key, _):as) = a : checkDup [r | r@(key', _) <- as, not (key `sameKey` key')]
+
+        sameKey :: [SExpr] -> [SExpr] -> Bool
+        sameKey as bs
+          | length as == length bs = and $ zipWith same as bs
+          | True                   = error $ "Data.SBV: Differing length of key received in chainAssigns: " ++ show (as, bs)
+
+        -- We don't want to derive Eq; as this is more careful on floats and such
+        same :: SExpr -> SExpr -> Bool
+        same x y = case (x, y) of
+                     (ECon a,      ECon b)       -> a == b
+                     (ENum (i, _), ENum (j, _))  -> i == j
+                     (EReal a,     EReal b)      -> algRealStructuralEqual a b
+                     (EFloat  f1,  EFloat  f2)   -> fpIsEqualObjectH f1 f2
+                     (EDouble d1,  EDouble d2)   -> fpIsEqualObjectH d1 d2
+                     (EApp as,     EApp bs)      -> length as == length bs && and (zipWith same as bs)
+                     (e1,          e2)           -> if eRank e1 == eRank e2
+                                                    then error $ "Data.SBV: You've found a bug in SBV! Please report: SExpr(same): " ++ show (e1, e2)
+                                                    else False
+        -- Defensive programming: It's too long to list all pair up, so we use this function and
+        -- GHC's pattern-match completion warning to catch cases we might've forgotten. If
+        -- you ever get the error line above fire, because you must've disabled the pattern-match
+        -- completion check warning! Shame on you.
+        eRank :: SExpr -> Int
+        eRank ECon{}    = 0
+        eRank ENum{}    = 1
+        eRank EReal{}   = 2
+        eRank EFloat{}  = 3
+        eRank EDouble{} = 4
+        eRank EApp{}    = 5
+
+{-# ANN chainAssigns ("HLint: ignore Redundant if" :: String) #-}
diff --git a/Data/SBV/Utils/TDiff.hs b/Data/SBV/Utils/TDiff.hs
--- a/Data/SBV/Utils/TDiff.hs
+++ b/Data/SBV/Utils/TDiff.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Data.SBV.Utils.TDiff
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/BitPrecise/BitTricks.hs b/Documentation/SBV/Examples/BitPrecise/BitTricks.hs
--- a/Documentation/SBV/Examples/BitPrecise/BitTricks.hs
+++ b/Documentation/SBV/Examples/BitPrecise/BitTricks.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.BitPrecise.BitTricks
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs b/Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs
--- a/Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs
+++ b/Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.BitPrecise.BrokenSearch
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -20,13 +20,13 @@
 --
 -- >>> checkArithOverflow midPointBroken
 -- Documentation/SBV/Examples/BitPrecise/BrokenSearch.hs:33:28:+!: SInt32 addition overflows: Violated. Model:
---   low  = 1073741824 :: Int32
---   high = 1073742336 :: Int32
+--   low  = 2147483583 :: Int32
+--   high = 2147483647 :: Int32
 --
 -- Indeed:
 --
--- >>> (1073741824 + 1073742336) `div` (2::Int32)
--- -1073741568
+-- >>> (2147483583 + 2147483647) `div` (2::Int32)
+-- -33
 --
 -- giving us a negative mid-point value!
 midPointBroken :: SInt32 -> SInt32 -> SInt32
@@ -101,3 +101,5 @@
                                         mid   = f low high
 
                                     return $ sFromIntegral mid .== mid'
+
+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Documentation/SBV/Examples/BitPrecise/Legato.hs b/Documentation/SBV/Examples/BitPrecise/Legato.hs
--- a/Documentation/SBV/Examples/BitPrecise/Legato.hs
+++ b/Documentation/SBV/Examples/BitPrecise/Legato.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.BitPrecise.Legato
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/BitPrecise/MergeSort.hs b/Documentation/SBV/Examples/BitPrecise/MergeSort.hs
--- a/Documentation/SBV/Examples/BitPrecise/MergeSort.hs
+++ b/Documentation/SBV/Examples/BitPrecise/MergeSort.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.BitPrecise.MergeSort
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/BitPrecise/MultMask.hs b/Documentation/SBV/Examples/BitPrecise/MultMask.hs
--- a/Documentation/SBV/Examples/BitPrecise/MultMask.hs
+++ b/Documentation/SBV/Examples/BitPrecise/MultMask.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.BitPrecise.MultMask
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -30,6 +30,7 @@
 module Documentation.SBV.Examples.BitPrecise.MultMask where
 
 import Data.SBV
+import Data.SBV.Control
 
 -- | Find the multiplier and the mask as described. We have:
 --
@@ -41,9 +42,17 @@
 -- That is, any 64 bit value masked by the first and multipled by the second
 -- value above will have its bits at positions @[7,15,23,31,39,47,55,63]@ moved
 -- to positions @[56,57,58,59,60,61,62,63]@ respectively.
+--
+-- Note that we have to send z3 custom configuration for this problem as
+-- otherwise it takes too long. See <http://github.com/Z3Prover/z3/issues/2075>
+-- for details.
 maskAndMult :: IO ()
 maskAndMult = print =<< satWith z3{printBase=16} find
-  where find = do mask <- exists "mask"
+  where find = do -- The magic incantations that make z3 go faster on this
+                  setOption $ OptionKeyword ":smt.auto_config" ["false"]
+                  setOption $ OptionKeyword ":smt.relevancy"   ["0"]
+
+                  mask <- exists "mask"
                   mult <- exists "mult"
                   inp  <- forall "inp"
                   let res = (mask .&. inp) * (mult :: SWord64)
diff --git a/Documentation/SBV/Examples/BitPrecise/PrefixSum.hs b/Documentation/SBV/Examples/BitPrecise/PrefixSum.hs
--- a/Documentation/SBV/Examples/BitPrecise/PrefixSum.hs
+++ b/Documentation/SBV/Examples/BitPrecise/PrefixSum.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.BitPrecise.PrefixSum
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/CodeGeneration/AddSub.hs b/Documentation/SBV/Examples/CodeGeneration/AddSub.hs
--- a/Documentation/SBV/Examples/CodeGeneration/AddSub.hs
+++ b/Documentation/SBV/Examples/CodeGeneration/AddSub.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.CodeGeneration.AddSub
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/CodeGeneration/CRC_USB5.hs b/Documentation/SBV/Examples/CodeGeneration/CRC_USB5.hs
--- a/Documentation/SBV/Examples/CodeGeneration/CRC_USB5.hs
+++ b/Documentation/SBV/Examples/CodeGeneration/CRC_USB5.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.CodeGeneration.CRC_USB5
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/CodeGeneration/Fibonacci.hs b/Documentation/SBV/Examples/CodeGeneration/Fibonacci.hs
--- a/Documentation/SBV/Examples/CodeGeneration/Fibonacci.hs
+++ b/Documentation/SBV/Examples/CodeGeneration/Fibonacci.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.CodeGeneration.Fibonacci
--- Author    : Lee Pike, Levent Erkok
+-- Copyright : (c) Lee Pike
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/CodeGeneration/GCD.hs b/Documentation/SBV/Examples/CodeGeneration/GCD.hs
--- a/Documentation/SBV/Examples/CodeGeneration/GCD.hs
+++ b/Documentation/SBV/Examples/CodeGeneration/GCD.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.CodeGeneration.GCD
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/CodeGeneration/PopulationCount.hs b/Documentation/SBV/Examples/CodeGeneration/PopulationCount.hs
--- a/Documentation/SBV/Examples/CodeGeneration/PopulationCount.hs
+++ b/Documentation/SBV/Examples/CodeGeneration/PopulationCount.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.CodeGeneration.PopulationCount
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/CodeGeneration/Uninterpreted.hs b/Documentation/SBV/Examples/CodeGeneration/Uninterpreted.hs
--- a/Documentation/SBV/Examples/CodeGeneration/Uninterpreted.hs
+++ b/Documentation/SBV/Examples/CodeGeneration/Uninterpreted.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.CodeGeneration.Uninterpreted
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Crypto/AES.hs b/Documentation/SBV/Examples/Crypto/AES.hs
--- a/Documentation/SBV/Examples/Crypto/AES.hs
+++ b/Documentation/SBV/Examples/Crypto/AES.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Crypto.AES
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Crypto/RC4.hs b/Documentation/SBV/Examples/Crypto/RC4.hs
--- a/Documentation/SBV/Examples/Crypto/RC4.hs
+++ b/Documentation/SBV/Examples/Crypto/RC4.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Crypto.RC4
--- Author    : Austin Seipp
+-- Copyright : (c) Austin Seipp
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Existentials/CRCPolynomial.hs b/Documentation/SBV/Examples/Existentials/CRCPolynomial.hs
--- a/Documentation/SBV/Examples/Existentials/CRCPolynomial.hs
+++ b/Documentation/SBV/Examples/Existentials/CRCPolynomial.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Existentials.CRCPolynomial
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Existentials/Diophantine.hs b/Documentation/SBV/Examples/Existentials/Diophantine.hs
--- a/Documentation/SBV/Examples/Existentials/Diophantine.hs
+++ b/Documentation/SBV/Examples/Existentials/Diophantine.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Existentials.Diophantine
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Lists/BoundedMutex.hs b/Documentation/SBV/Examples/Lists/BoundedMutex.hs
--- a/Documentation/SBV/Examples/Lists/BoundedMutex.hs
+++ b/Documentation/SBV/Examples/Lists/BoundedMutex.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Lists.BoundedMutex
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -72,7 +72,7 @@
                                   ok   = ite (prev .== idle)                          (cur `sElem` [idle, ready])
                                        $ ite (prev .== ready .&& turn .== literal me) (cur `sElem` [critical])
                                        $ ite (prev .== critical)                      (cur `sElem` [critical, idle])
-                                       $                                              (cur `sElem` [prev])
+                                                                                      (cur `sElem` [prev])
                               in ok .&& check (i-1) turns rest cur
 
 -- | The mutex algorithm, coded implicity as an assignment to turns. Turns start at @1@, and at each stage is either
diff --git a/Documentation/SBV/Examples/Lists/Fibonacci.hs b/Documentation/SBV/Examples/Lists/Fibonacci.hs
--- a/Documentation/SBV/Examples/Lists/Fibonacci.hs
+++ b/Documentation/SBV/Examples/Lists/Fibonacci.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Lists.Fibonacci
--- Author    : Joel Burget
+-- Copyright : (c) Joel Burget
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Lists/Nested.hs b/Documentation/SBV/Examples/Lists/Nested.hs
--- a/Documentation/SBV/Examples/Lists/Nested.hs
+++ b/Documentation/SBV/Examples/Lists/Nested.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Lists.Nested
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Misc/Auxiliary.hs b/Documentation/SBV/Examples/Misc/Auxiliary.hs
--- a/Documentation/SBV/Examples/Misc/Auxiliary.hs
+++ b/Documentation/SBV/Examples/Misc/Auxiliary.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.Auxiliary
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Misc/Enumerate.hs b/Documentation/SBV/Examples/Misc/Enumerate.hs
--- a/Documentation/SBV/Examples/Misc/Enumerate.hs
+++ b/Documentation/SBV/Examples/Misc/Enumerate.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.Enumerate
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Misc/Floating.hs b/Documentation/SBV/Examples/Misc/Floating.hs
--- a/Documentation/SBV/Examples/Misc/Floating.hs
+++ b/Documentation/SBV/Examples/Misc/Floating.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.Floating
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -56,19 +56,19 @@
 --
 -- >>> assocPlusRegular
 -- Falsifiable. Counter-example:
---   x =  3.7634227e-37 :: Float
---   y = -3.7612938e-37 :: Float
---   z = -1.1036833e-38 :: Float
+--   x =  4.4272186e20 :: Float
+--   y =  1.6717353e20 :: Float
+--   z = -1.2626838e19 :: Float
 --
 -- Indeed, we have:
 --
--- >>> let  x =  3.7634227e-37 :: Float
--- >>> let  y = -3.7612938e-37 :: Float
--- >>> let  z = -1.1036833e-38 :: Float
+-- >>> let x =  4.4272186e20 :: Float
+-- >>> let y =  1.6717353e20 :: Float
+-- >>> let z = -1.2626838e19 :: Float
 -- >>> x + (y + z)
--- -1.0823943e-38
+-- 5.972685e20
 -- >>> (x + y) + z
--- -1.0823947e-38
+-- 5.972686e20
 --
 -- Note the difference between two additions!
 assocPlusRegular :: IO ThmResult
@@ -90,17 +90,17 @@
 --
 -- >>> nonZeroAddition
 -- Falsifiable. Counter-example:
---   a =  -4.611686e18 :: Float
---   b = 1.3552526e-20 :: Float
+--   a =  1.8446744e19 :: Float
+--   b = -3.786532e-28 :: Float
 --
 -- Indeed, we have:
 --
--- >>> (-4.611686e18 + 1.3552526e-20) == (-4.611686e18 :: Float)
+-- >>> (1.8446744e19 - 3.786532e-28) == (1.8446744e19 :: Float)
 -- True
 --
 -- But:
 --
--- >>> 1.3552526e-20 == (0 :: Float)
+-- >>> -3.786532e-28 == (0 :: Float)
 -- False
 --
 nonZeroAddition :: IO ThmResult
@@ -121,13 +121,13 @@
 --
 -- >>> multInverse
 -- Falsifiable. Counter-example:
---   a = 8.988465676670122e307 :: Double
+--   a = 1.271703601976025e-308 :: Double
 --
 -- Indeed, we have:
 --
--- >>> let a = 8.988465676670122e307 :: Double
+-- >>> let a = 1.271703601976025e-308 :: Double
 -- >>> a * (1/a)
--- 1.0000000000000002
+-- 0.9999999999999999
 multInverse :: IO ThmResult
 multInverse = prove $ do a <- sDouble "a"
                          constrain $ fpIsPoint a
diff --git a/Documentation/SBV/Examples/Misc/ModelExtract.hs b/Documentation/SBV/Examples/Misc/ModelExtract.hs
--- a/Documentation/SBV/Examples/Misc/ModelExtract.hs
+++ b/Documentation/SBV/Examples/Misc/ModelExtract.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.ModelExtract
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Misc/NoDiv0.hs b/Documentation/SBV/Examples/Misc/NoDiv0.hs
--- a/Documentation/SBV/Examples/Misc/NoDiv0.hs
+++ b/Documentation/SBV/Examples/Misc/NoDiv0.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.NoDiv0
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Misc/Polynomials.hs b/Documentation/SBV/Examples/Misc/Polynomials.hs
--- a/Documentation/SBV/Examples/Misc/Polynomials.hs
+++ b/Documentation/SBV/Examples/Misc/Polynomials.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.Polynomials
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Misc/SetAlgebra.hs b/Documentation/SBV/Examples/Misc/SetAlgebra.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Misc/SetAlgebra.hs
@@ -0,0 +1,376 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Misc.SetAlgebra
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proves various algebraic properties of sets using SBV. The properties we
+-- prove all come from <http://en.wikipedia.org/wiki/Algebra_of_sets>.
+-----------------------------------------------------------------------------
+
+module Documentation.SBV.Examples.Misc.SetAlgebra where
+
+import Data.SBV hiding (complement)
+import Data.SBV.Set ()   -- This import shouldn't be necessary, but I can't get doctest to work otherwise. Sigh.
+
+-- $setup
+-- >>> -- For doctest purposes only:
+-- >>> import Data.SBV hiding (complement)
+-- >>> import Data.SBV.Set
+-- >>> :set -XScopedTypeVariables
+
+-- | Abbreviation for set of integers. For convenience only in monomorphising the properties.
+type SI = SSet Integer
+
+-- * Commutativity
+-- $commutativity
+{- $commutativity
+\(A\cup B=B\cup A\)
+
+>>> prove $ \(a :: SI) b -> a `union` b .== b `union` a
+Q.E.D.
+
+\(A\cap B=B\cap A\)
+
+>>> prove $ \(a :: SI) b -> a `intersection` b .== b `intersection` a
+Q.E.D.
+-}
+
+-- * Associativity
+-- $associativity
+{- $associativity
+
+\((A\cup B)\cup C=A\cup (B\cup C)\)
+
+>>> prove $ \(a :: SI) b c -> a `union` (b `union` c) .== (a `union` b) `union` c
+Q.E.D.
+
+\((A\cap B)\cap C=A\cap (B\cap C)\)
+
+>>> prove $ \(a :: SI) b c -> a `intersection` (b `intersection` c) .== (a `intersection` b) `intersection` c
+Q.E.D.
+-}
+
+-- * Distributivity
+-- $distributivity
+{- $distributivity
+\(A\cup (B\cap C)=(A\cup B)\cap (A\cup C)\)
+
+>>> prove $ \(a :: SI) b c -> a `union` (b `intersection` c) .== (a `union` b) `intersection` (a `union` c)
+Q.E.D.
+
+\(A\cap (B\cup C)=(A\cap B)\cup (A\cap C)\)
+
+>>> prove $ \(a :: SI) b c -> a `intersection` (b `union` c) .== (a `intersection` b) `union` (a `intersection` c)
+Q.E.D.
+-}
+
+-- * Identity properties
+-- $identity
+{- $identity
+
+\(A\cup \varnothing = A\)
+
+>>> prove $ \(a :: SI) -> a `union` empty .== a
+Q.E.D.
+
+\(A\cap U = A \)
+
+>>> prove $ \(a :: SI) -> a `intersection` full .== a
+Q.E.D.
+-}
+
+-- * Complement properties
+-- $complement
+{- $complement
+
+\( A\cup A^{C}=U \)
+
+>>> prove $ \(a :: SI) -> a `union` complement a .== full
+Q.E.D.
+
+\( A\cap A^{C}=\varnothing \)
+
+>>> prove $ \(a :: SI) -> a `intersection` complement a .== empty
+Q.E.D.
+
+\({(A^{C})}^{C}=A\)
+
+>>> prove $ \(a :: SI) -> complement (complement a) .== a
+Q.E.D.
+
+\(\varnothing ^{C}=U\)
+
+>>> prove $ complement (empty :: SI) .== full
+Q.E.D.
+
+\( U^{C}=\varnothing \)
+
+>>> prove $ complement (full :: SI) .== empty
+Q.E.D.
+-}
+
+-- * Uniqueness of the complement
+--
+-- $compUnique
+{- $compUnique
+The complement of a set is the only set that satisfies the first two complement properties above. That
+is complementation is characterized by those two laws, as we can formally establish:
+
+\( A\cup B=U \land A\cap B=\varnothing \iff B=A^{C} \)
+
+>>> prove $ \(a :: SI) b -> a `union` b .== full .&& a `intersection` b .== empty .<=> b .== complement a
+Q.E.D.
+-}
+
+-- * Idempotency
+-- $idempotent
+{- $idempotent
+
+\( A\cup A=A \)
+
+>>> prove $ \(a :: SI) -> a `union` a .== a
+Q.E.D.
+
+\( A\cap A=A \)
+
+>>> prove $ \(a :: SI) -> a `intersection` a .== a
+Q.E.D.
+-}
+
+-- * Domination properties
+-- $domination
+{- $domination
+
+\( A\cup U=U \)
+
+>>> prove $ \(a :: SI) -> a `union` full .== full
+Q.E.D.
+
+\( A\cap \varnothing =\varnothing \)
+
+>>> prove $ \(a :: SI) -> a `intersection` empty .== empty
+Q.E.D.
+-}
+
+-- * Absorption properties
+-- $absorption
+{- $absorption
+
+\( A\cup (A\cap B)=A \)
+
+>>> prove $ \(a :: SI) b -> a `union` (a `intersection` b) .== a
+Q.E.D.
+
+\( A\cap (A\cup B)=A \)
+
+>>> prove $ \(a :: SI) b -> a `intersection` (a `union` b) .== a
+Q.E.D.
+-}
+
+-- * Intersection and set difference
+-- $intdiff
+{- $intdiff
+
+\( A\cap B=A\setminus (A\setminus B) \)
+
+>>> prove $ \(a :: SI) b -> a `intersection` b .== a `difference` (a `difference` b)
+Q.E.D.
+-}
+
+-- * De Morgan's laws
+-- $deMorgan
+{- $deMorgan
+
+\( (A\cup B)^{C}=A^{C}\cap B^{C} \)
+
+>>> prove $ \(a :: SI) b -> complement (a `union` b) .== complement a `intersection` complement b
+Q.E.D.
+
+\( (A\cap B)^{C}=A^{C}\cup B^{C} \)
+
+>>> prove $ \(a :: SI) b -> complement (a `intersection` b) .== complement a `union` complement b
+Q.E.D.
+-}
+
+-- * Inclusion is a partial order
+-- $incPO
+{- $incPO
+Subset inclusion is a partial order, i.e., it is reflexive, antisymmetric, and transitive:
+
+\( A \subseteq A \)
+
+>>> prove $ \(a :: SI) -> a `isSubsetOf` a
+Q.E.D.
+
+\( A\subseteq B \land B\subseteq A \iff A = B \)
+
+>>> prove $ \(a :: SI) b -> a `isSubsetOf` b .&& b `isSubsetOf` a .<=> a .== b
+Q.E.D.
+
+\( A\subseteq B \land B\subseteq C \Rightarrow A \subseteq C \)
+
+>>> prove $ \(a :: SI) b c -> a `isSubsetOf` b .&& b `isSubsetOf` c .=> a `isSubsetOf` c
+Q.E.D.
+-}
+
+-- * Joins and meets
+-- $joinMeet
+{- $joinMeet
+
+\( A\subseteq A\cup B \)
+
+>>> prove $ \(a :: SI) b -> a `isSubsetOf` (a `union` b)
+Q.E.D.
+
+
+\( A\subseteq C \land B\subseteq C \Rightarrow (A \cup B) \subseteq C \)
+
+>>> prove $ \(a :: SI) b c -> a `isSubsetOf` c .&& b `isSubsetOf` c .=> (a `union` b) `isSubsetOf` c
+Q.E.D.
+
+\( A\cap B\subseteq A \)
+
+>>> prove $ \(a :: SI) b -> (a `intersection` b) `isSubsetOf` a
+Q.E.D.
+
+\( A\cap B\subseteq B \)
+
+>>> prove $ \(a :: SI) b -> (a `intersection` b) `isSubsetOf` b
+Q.E.D.
+
+\( C\subseteq A \land C\subseteq B \Rightarrow C \subseteq (A \cap B) \)
+
+>>> prove $ \(a :: SI) b c -> c `isSubsetOf` a .&& c `isSubsetOf` b .=> c `isSubsetOf` (a `intersection` b)
+Q.E.D.
+-}
+
+-- * Subset characterization
+-- $subsetChar
+{- $subsetChar
+There are multiple equivalent ways of characterizing the subset relationship:
+
+\( A\subseteq B  \iff A \cap B = A \) 
+
+>>> prove $ \(a :: SI) b -> a `isSubsetOf` b .<=> a `intersection` b .== a
+Q.E.D.
+
+
+\( A\subseteq B \iff A \cup B = B \) 
+
+>>> prove $ \(a :: SI) b -> a `isSubsetOf` b .<=> a `union` b .== b
+Q.E.D.
+
+\( A\subseteq B \iff A \setminus B = \varnothing \)
+
+>>> prove $ \(a :: SI) b -> a `isSubsetOf` b .<=> a `difference` b .== empty
+Q.E.D.
+
+\( A\subseteq B \iff B^{C} \subseteq A^{C} \)
+
+>>> prove $ \(a :: SI) b -> a `isSubsetOf` b .<=> complement b `isSubsetOf` complement a
+Q.E.D.
+-}
+
+-- * Relative complements
+-- $relComp
+{- $relComp
+
+\( C\setminus (A\cap B)=(C\setminus A)\cup (C\setminus B) \)
+
+>>> prove $ \(a :: SI) b c -> c \\ (a `intersection` b) .== (c \\ a) `union` (c \\ b)
+Q.E.D.
+
+\( C\setminus (A\cup B)=(C\setminus A)\cap (C\setminus B) \)
+
+>>> prove $ \(a :: SI) b c -> c \\ (a `union` b) .== (c \\ a) `intersection` (c \\ b)
+Q.E.D.
+
+
+\( \displaystyle C\setminus (B\setminus A)=(A\cap C)\cup (C\setminus B) \)
+
+>>> prove $ \(a :: SI) b c -> c \\ (b \\ a) .== (a `intersection` c) `union` (c \\ b)
+Q.E.D.
+
+\( (B\setminus A)\cap C = (B\cap C)\setminus A \)
+
+>>> prove $ \(a :: SI) b c -> (b \\ a) `intersection` c .== (b `intersection` c) \\ a
+Q.E.D.
+
+\( (B\setminus A)\cap C= B\cap (C\setminus A) \)
+
+>>> prove $ \(a :: SI) b c -> (b \\ a) `intersection` c .== b `intersection` (c \\ a)
+Q.E.D.
+
+\( (B\setminus A)\cup C=(B\cup C)\setminus (A\setminus C) \)
+
+>>> prove $ \(a :: SI) b c -> (b \\ a) `union` c .== (b `union` c) \\ (a \\ c)
+Q.E.D.
+
+
+\( A \setminus A = \varnothing \)
+
+>>> prove $ \(a :: SI) -> a \\ a .== empty
+Q.E.D.
+
+\( \varnothing \setminus A = \varnothing \)
+
+>>> prove $ \(a :: SI) -> empty \\ a .== empty
+Q.E.D.
+
+\( A \setminus \varnothing = A \)
+
+>>> prove $ \(a :: SI) -> a \\ empty .== a
+Q.E.D.
+
+\( B \setminus A = A^{C} \cap B \)
+
+>>> prove $ \(a :: SI) b -> b \\ a .== complement a `intersection` b
+Q.E.D.
+
+\( {(B \setminus A)}^{C} = A \cup B^{C} \)
+
+>>> prove $ \(a :: SI) b -> complement (b \\ a) .== a `union` complement b
+Q.E.D.
+
+\( U \setminus A = A^{C} \)
+
+>>> prove $ \(a :: SI) -> full \\ a .== complement a
+Q.E.D.
+
+
+\( A \setminus U = \varnothing \)
+
+>>> prove $ \(a :: SI) -> a \\ full .== empty
+Q.E.D.
+-}
+
+-- * Distributing subset relation
+-- $distSubset
+{- $distSubset
+
+A common mistake newcomers to set theory make is to distribute the subset relationship over intersection
+and unions, which is only true as described above. Here, we use SBV to show two incorrect cases:
+
+Subset relation does /not/ distribute over union on the left:
+
+\(A \subseteq (B \cup C) \nRightarrow A \subseteq B \land A \subseteq C \)
+
+>>> prove $ \(a :: SI) b c -> a `isSubsetOf` (b `union` c) .=> a `isSubsetOf` b .&& a `isSubsetOf` c
+Falsifiable. Counter-example:
+  s0 =     {0} :: {Integer}
+  s1 =       U :: {Integer}
+  s2 = U - {0} :: {Integer}
+
+Similarly, subset relation does /not/ distribute over intersection on the right:
+
+\( (B \cap C) \subseteq A \nRightarrow B \subseteq A \land C \subseteq A \)
+
+>>> prove $ \(a :: SI) b c -> (b `intersection` c) `isSubsetOf` a .=> b `isSubsetOf` a .&& c `isSubsetOf` a
+Falsifiable. Counter-example:
+  s0 =      {} :: {Integer}
+  s1 = U - {0} :: {Integer}
+  s2 =     {0} :: {Integer}
+-}
diff --git a/Documentation/SBV/Examples/Misc/SoftConstrain.hs b/Documentation/SBV/Examples/Misc/SoftConstrain.hs
--- a/Documentation/SBV/Examples/Misc/SoftConstrain.hs
+++ b/Documentation/SBV/Examples/Misc/SoftConstrain.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.SoftConstrain
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Misc/Tuple.hs b/Documentation/SBV/Examples/Misc/Tuple.hs
--- a/Documentation/SBV/Examples/Misc/Tuple.hs
+++ b/Documentation/SBV/Examples/Misc/Tuple.hs
@@ -1,7 +1,8 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.Tuple
--- Author    : Joel Burget, Levent Erkok
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Misc/Word4.hs b/Documentation/SBV/Examples/Misc/Word4.hs
--- a/Documentation/SBV/Examples/Misc/Word4.hs
+++ b/Documentation/SBV/Examples/Misc/Word4.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Misc.Word4
--- Author    : Brian Huffman
+-- Copyright : (c) Brian Huffman
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -41,7 +41,7 @@
 instance Read Word4 where
   readsPrec p s = [ (word4 x, s') | (x, s') <- readsPrec p s ]
 
--- | Bounded instance; from 0 to 255
+-- | Bounded instance; from 0 to 15
 instance Bounded Word4 where
   minBound = Word4 0x00
   maxBound = Word4 0x0f
diff --git a/Documentation/SBV/Examples/Optimization/Enumerate.hs b/Documentation/SBV/Examples/Optimization/Enumerate.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Optimization/Enumerate.hs
@@ -0,0 +1,97 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Optimization.Enumerate
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates how enumerations can be used with optimization,
+-- by properly defining your metric values.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass      #-}
+{-# LANGUAGE DeriveDataTypeable  #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving  #-}
+{-# LANGUAGE TemplateHaskell     #-}
+{-# LANGUAGE TypeFamilies        #-}
+
+module Documentation.SBV.Examples.Optimization.Enumerate where
+
+import Data.SBV
+
+-- | A simple enumeration
+data Day = Mon | Tue | Wed | Thu | Fri | Sat | Sun
+
+-- | Make 'Day' a symbolic value.
+mkSymbolicEnumeration ''Day
+
+-- | Give a name to the symbolic variants of 'Day', for convenience
+type SDay = SBV Day
+
+-- | Make day an optimizable value, by mapping it to 'Word8' in the most
+-- obvious way. We can map it to any value the underlying solver can optimize,
+-- but 'Word8' is the simplest and it'll fit the bill.
+instance Metric Day where
+  type MetricSpace Day = Word8
+
+  toMetricSpace x   = ite (x .== literal Mon) 0
+                    $ ite (x .== literal Tue) 1
+                    $ ite (x .== literal Wed) 2
+                    $ ite (x .== literal Thu) 3
+                    $ ite (x .== literal Fri) 4
+                    $ ite (x .== literal Sat) 5
+                                              6
+
+  fromMetricSpace x = ite (x .== 0) (literal Mon)
+                    $ ite (x .== 1) (literal Tue)
+                    $ ite (x .== 2) (literal Wed)
+                    $ ite (x .== 3) (literal Thu)
+                    $ ite (x .== 4) (literal Fri)
+                    $ ite (x .== 5) (literal Sat)
+                                    (literal Sun)
+
+-- | Identify weekend days
+isWeekend :: SDay -> SBool
+isWeekend = (`sElem` weekend)
+  where weekend = map literal [Sat, Sun]
+
+-- | Using optimization, find the latest day that is not a weekend.
+-- We have:
+--
+-- >>> almostWeekend
+-- Optimal model:
+--   almostWeekend = Fri :: Day
+--   last-day      =   4 :: Word8
+almostWeekend :: IO OptimizeResult
+almostWeekend = optimize Lexicographic $ do
+                    day <- free "almostWeekend"
+                    constrain $ sNot (isWeekend day)
+                    maximize "last-day" day
+
+-- | Using optimization, find the first day after the weekend.
+-- We have:
+--
+-- >>> weekendJustOver
+-- Optimal model:
+--   weekendJustOver = Mon :: Day
+--   first-day       =   0 :: Word8
+weekendJustOver :: IO OptimizeResult
+weekendJustOver = optimize Lexicographic $ do
+                      day <- free "weekendJustOver"
+                      constrain $ sNot (isWeekend day)
+                      minimize "first-day" day
+
+-- | Using optimization, find the first weekend day:
+-- We have:
+--
+-- >>> firstWeekend
+-- Optimal model:
+--   firstWeekend  = Sat :: Day
+--   first-weekend =   5 :: Word8
+firstWeekend :: IO OptimizeResult
+firstWeekend = optimize Lexicographic $ do
+                      day <- free "firstWeekend"
+                      constrain $ isWeekend day
+                      minimize "first-weekend" day
diff --git a/Documentation/SBV/Examples/Optimization/ExtField.hs b/Documentation/SBV/Examples/Optimization/ExtField.hs
--- a/Documentation/SBV/Examples/Optimization/ExtField.hs
+++ b/Documentation/SBV/Examples/Optimization/ExtField.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Optimization.ExtField
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Optimization/LinearOpt.hs b/Documentation/SBV/Examples/Optimization/LinearOpt.hs
--- a/Documentation/SBV/Examples/Optimization/LinearOpt.hs
+++ b/Documentation/SBV/Examples/Optimization/LinearOpt.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Optimization.LinearOpt
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Optimization/Production.hs b/Documentation/SBV/Examples/Optimization/Production.hs
--- a/Documentation/SBV/Examples/Optimization/Production.hs
+++ b/Documentation/SBV/Examples/Optimization/Production.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Optimization.Production
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Optimization/VM.hs b/Documentation/SBV/Examples/Optimization/VM.hs
--- a/Documentation/SBV/Examples/Optimization/VM.hs
+++ b/Documentation/SBV/Examples/Optimization/VM.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Optimization.VM
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/ProofTools/BMC.hs b/Documentation/SBV/Examples/ProofTools/BMC.hs
--- a/Documentation/SBV/Examples/ProofTools/BMC.hs
+++ b/Documentation/SBV/Examples/ProofTools/BMC.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.ProofTools.BMC
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -18,6 +18,8 @@
 -- What if @y@ starts at @11@?
 -----------------------------------------------------------------------------
 
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveTraversable     #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns        #-}
@@ -32,6 +34,7 @@
 
 -- | System state, containing the two integers.
 data S a = S { x :: a, y :: a }
+         deriving (Functor, Foldable, Traversable)
 
 -- | Show the state as a pair
 instance Show a => Show (S a) where
@@ -41,10 +44,9 @@
 instance EqSymbolic a => EqSymbolic (S a) where
    S {x = x1, y = y1} .== S {x = x2, y = y2} = x1 .== x2 .&& y1 .== y2
 
--- | Queriable instance for our state
-instance Queriable IO (S SInteger) (S Integer) where
-  fresh           = S <$> freshVar_  <*> freshVar_
-  extract S{x, y} = S <$> getValue x <*> getValue y
+-- | 'Fresh' instance for our state
+instance Fresh IO (S SInteger) where
+  fresh = S <$> freshVar_ <*> freshVar_
 
 -- * Encoding the problem
 
diff --git a/Documentation/SBV/Examples/ProofTools/Fibonacci.hs b/Documentation/SBV/Examples/ProofTools/Fibonacci.hs
--- a/Documentation/SBV/Examples/ProofTools/Fibonacci.hs
+++ b/Documentation/SBV/Examples/ProofTools/Fibonacci.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.ProofTools.Fibonacci
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -23,7 +23,9 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveFoldable        #-}
 {-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns        #-}
@@ -41,12 +43,11 @@
 -- | System state. We simply have two components, parameterized
 -- over the type so we can put in both concrete and symbolic values.
 data S a = S { i :: a, k :: a, m :: a, n :: a }
-         deriving (Show, Mergeable, Generic)
+         deriving (Show, Mergeable, Generic, Functor, Foldable, Traversable)
 
--- | Make our state queriable
-instance Queriable IO (S SInteger) (S Integer) where
+-- | 'Fresh' instance for our state
+instance Fresh IO (S SInteger) where
    fresh = S <$> freshVar_ <*> freshVar_ <*> freshVar_ <*> freshVar_
-   extract S{i, k, m, n} = S <$> getValue i <*> getValue k <*> getValue m <*> getValue n
 
 -- | Encoding partial correctness of the sum algorithm. We have:
 --
diff --git a/Documentation/SBV/Examples/ProofTools/Strengthen.hs b/Documentation/SBV/Examples/ProofTools/Strengthen.hs
--- a/Documentation/SBV/Examples/ProofTools/Strengthen.hs
+++ b/Documentation/SBV/Examples/ProofTools/Strengthen.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.ProofTools.Strengthen
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -29,6 +29,8 @@
 -- in Bradley's paper quite closely.
 -----------------------------------------------------------------------------
 
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveTraversable     #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns        #-}
@@ -43,12 +45,12 @@
 
 -- | System state. We simply have two components, parameterized
 -- over the type so we can put in both concrete and symbolic values.
-data S a = S { x :: a, y :: a } deriving Show
+data S a = S { x :: a, y :: a }
+         deriving (Show, Functor, Foldable, Traversable)
 
--- | Make our state queriable
-instance Queriable IO (S SInteger) (S Integer) where
+-- | 'Fresh' instance for our state
+instance Fresh IO (S SInteger) where
   fresh = S <$> freshVar_ <*> freshVar_
-  extract S{x, y} = S <$> getValue x <*> getValue y
 
 -- * Encoding the problem
 
diff --git a/Documentation/SBV/Examples/ProofTools/Sum.hs b/Documentation/SBV/Examples/ProofTools/Sum.hs
--- a/Documentation/SBV/Examples/ProofTools/Sum.hs
+++ b/Documentation/SBV/Examples/ProofTools/Sum.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.ProofTools.Sum
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -22,7 +22,9 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveFoldable        #-}
 {-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE NamedFieldPuns        #-}
@@ -39,12 +41,11 @@
 
 -- | System state. We simply have two components, parameterized
 -- over the type so we can put in both concrete and symbolic values.
-data S a = S { s :: a, i :: a, n :: a } deriving (Show, Mergeable, Generic)
+data S a = S { s :: a, i :: a, n :: a } deriving (Show, Mergeable, Generic, Functor, Foldable, Traversable)
 
--- | Queriable instance for our state
-instance Queriable IO (S SInteger) (S Integer) where
-  fresh              = S <$> freshVar_  <*> freshVar_  <*> freshVar_
-  extract S{s, i, n} = S <$> getValue s <*> getValue i <*> getValue n
+-- | 'Fresh' instance for our state
+instance Fresh IO (S SInteger) where
+  fresh  = S <$> freshVar_  <*> freshVar_  <*> freshVar_
 
 -- | Encoding partial correctness of the sum algorithm. We have:
 --
diff --git a/Documentation/SBV/Examples/Puzzles/Birthday.hs b/Documentation/SBV/Examples/Puzzles/Birthday.hs
--- a/Documentation/SBV/Examples/Puzzles/Birthday.hs
+++ b/Documentation/SBV/Examples/Puzzles/Birthday.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.Birthday
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/Coins.hs b/Documentation/SBV/Examples/Puzzles/Coins.hs
--- a/Documentation/SBV/Examples/Puzzles/Coins.hs
+++ b/Documentation/SBV/Examples/Puzzles/Coins.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.Coins
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/Counts.hs b/Documentation/SBV/Examples/Puzzles/Counts.hs
--- a/Documentation/SBV/Examples/Puzzles/Counts.hs
+++ b/Documentation/SBV/Examples/Puzzles/Counts.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.Counts
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -56,9 +56,9 @@
 --
 -- >>> counts
 -- Solution #1
--- In this sentence, the number of occurrences of 0 is 1, of 1 is 7, of 2 is 3, of 3 is 2, of 4 is 1, of 5 is 1, of 6 is 1, of 7 is 2, of 8 is 1, of 9 is 1.
--- Solution #2
 -- In this sentence, the number of occurrences of 0 is 1, of 1 is 11, of 2 is 2, of 3 is 1, of 4 is 1, of 5 is 1, of 6 is 1, of 7 is 1, of 8 is 1, of 9 is 1.
+-- Solution #2
+-- In this sentence, the number of occurrences of 0 is 1, of 1 is 7, of 2 is 3, of 3 is 2, of 4 is 1, of 5 is 1, of 6 is 1, of 7 is 2, of 8 is 1, of 9 is 1.
 -- Found: 2 solution(s).
 counts :: IO ()
 counts = do res <- allSat $ puzzle `fmap` mkExistVars 10
diff --git a/Documentation/SBV/Examples/Puzzles/DogCatMouse.hs b/Documentation/SBV/Examples/Puzzles/DogCatMouse.hs
--- a/Documentation/SBV/Examples/Puzzles/DogCatMouse.hs
+++ b/Documentation/SBV/Examples/Puzzles/DogCatMouse.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.DogCatMouse
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/Euler185.hs b/Documentation/SBV/Examples/Puzzles/Euler185.hs
--- a/Documentation/SBV/Examples/Puzzles/Euler185.hs
+++ b/Documentation/SBV/Examples/Puzzles/Euler185.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.Euler185
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/Fish.hs b/Documentation/SBV/Examples/Puzzles/Fish.hs
--- a/Documentation/SBV/Examples/Puzzles/Fish.hs
+++ b/Documentation/SBV/Examples/Puzzles/Fish.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.Fish
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -74,8 +74,10 @@
 --
 -- It's not hard to modify this program to grab the values of all the assignments, i.e., the full
 -- solution to the puzzle. We leave that as an exercise to the interested reader!
+-- NB. We use the 'satTrackUFs' configuration to indicate that the uninterpreted function
+-- changes do not matter for generating different values. All we care is that the fishOwner changes!
 fishOwner :: IO ()
-fishOwner = do vs <- getModelValues "fishOwner" `fmap` allSat puzzle
+fishOwner = do vs <- getModelValues "fishOwner" `fmap` allSatWith z3{satTrackUFs = False} puzzle
                case vs of
                  [Just (v::Nationality)] -> print v
                  []                      -> error "no solution"
diff --git a/Documentation/SBV/Examples/Puzzles/Garden.hs b/Documentation/SBV/Examples/Puzzles/Garden.hs
--- a/Documentation/SBV/Examples/Puzzles/Garden.hs
+++ b/Documentation/SBV/Examples/Puzzles/Garden.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.Garden
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -68,11 +68,9 @@
 
             let valid = validPick n
 
-            -- Declare three existential flowers. We name these with
-            -- the suffix "_modelIgnore" as we don't consider variations
-            -- on them to be interesting for model construction purposes.
-            -- We'll use the 'isNonModelVar' parameter to ignore them
-            -- for that purpose.
+            -- Declare three existential flowers. We declar these with
+            -- _modelIgnore suffix, because we don't care different assignments
+            -- to them to be a different model. See 'isNonModelVar' below.
             ef1 <- exists "ef1_modelIgnore"
             ef2 <- exists "ef2_modelIgnore"
             ef3 <- exists "ef3_modelIgnore"
@@ -104,7 +102,7 @@
 -- This is the only solution. (Unique up to prefix existentials.)
 --
 -- So, a garden with 3 flowers is the only solution. (Note that we simply skip
--- over the prefix existentials for model purposes here, as they don't represent
--- a different solution.)
+-- over the prefix existentials and the assignments to uninterpreted function 'col'
+-- for model purposes here, as they don't represent a different solution.)
 flowerCount :: IO ()
-flowerCount = print =<< allSatWith z3{isNonModelVar = ("_modelIgnore" `isSuffixOf`)} puzzle
+flowerCount = print =<< allSatWith z3{satTrackUFs = False, isNonModelVar = ("_modelIgnore" `isSuffixOf`)} puzzle
diff --git a/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs b/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs
--- a/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs
+++ b/Documentation/SBV/Examples/Puzzles/HexPuzzle.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.HexPuzzle
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -116,7 +116,7 @@
                                       cs <- checkSat
                                       case cs of
                                        Unk   -> error "Unknown!"
-                                       Unsat -> io $ putStrLn $ "There are no more solutions."
+                                       Unsat -> io $ putStrLn "There are no more solutions."
                                        Sat   -> do newVals <- mapM getValue vs
                                                    io $ putStrLn $ "Found: " ++ show newVals
                                                    go newVals
diff --git a/Documentation/SBV/Examples/Puzzles/LadyAndTigers.hs b/Documentation/SBV/Examples/Puzzles/LadyAndTigers.hs
--- a/Documentation/SBV/Examples/Puzzles/LadyAndTigers.hs
+++ b/Documentation/SBV/Examples/Puzzles/LadyAndTigers.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.LadyAndTigers
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/MagicSquare.hs b/Documentation/SBV/Examples/Puzzles/MagicSquare.hs
--- a/Documentation/SBV/Examples/Puzzles/MagicSquare.hs
+++ b/Documentation/SBV/Examples/Puzzles/MagicSquare.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.MagicSquare
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/NQueens.hs b/Documentation/SBV/Examples/Puzzles/NQueens.hs
--- a/Documentation/SBV/Examples/Puzzles/NQueens.hs
+++ b/Documentation/SBV/Examples/Puzzles/NQueens.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.NQueens
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/SendMoreMoney.hs b/Documentation/SBV/Examples/Puzzles/SendMoreMoney.hs
--- a/Documentation/SBV/Examples/Puzzles/SendMoreMoney.hs
+++ b/Documentation/SBV/Examples/Puzzles/SendMoreMoney.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.SendMoreMoney
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/Sudoku.hs b/Documentation/SBV/Examples/Puzzles/Sudoku.hs
--- a/Documentation/SBV/Examples/Puzzles/Sudoku.hs
+++ b/Documentation/SBV/Examples/Puzzles/Sudoku.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.Sudoku
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Puzzles/U2Bridge.hs b/Documentation/SBV/Examples/Puzzles/U2Bridge.hs
--- a/Documentation/SBV/Examples/Puzzles/U2Bridge.hs
+++ b/Documentation/SBV/Examples/Puzzles/U2Bridge.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Puzzles.U2Bridge
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -15,7 +15,6 @@
 {-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE StandaloneDeriving   #-}
 {-# LANGUAGE TemplateHaskell      #-}
-{-# LANGUAGE TypeSynonymInstances #-}
 
 module Documentation.SBV.Examples.Puzzles.U2Bridge where
 
@@ -253,7 +252,7 @@
         -- same order and thus not mess up our test suite if the
         -- solver decides to return them in the alternate order
         rearrange :: AllSatResult -> AllSatResult
-        rearrange (AllSatResult (b1, b2, ms)) = AllSatResult (b1, b2, sortOn (show . SatResult) ms)
+        rearrange (AllSatResult (b1, b2, b3, ms)) = AllSatResult (b1, b2, b3, sortOn (show . SatResult) ms)
 
 -- | Solve the U2-bridge crossing puzzle, starting by testing solutions with
 -- increasing number of steps, until we find one. We have:
diff --git a/Documentation/SBV/Examples/Queries/AllSat.hs b/Documentation/SBV/Examples/Queries/AllSat.hs
--- a/Documentation/SBV/Examples/Queries/AllSat.hs
+++ b/Documentation/SBV/Examples/Queries/AllSat.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Queries.AllSat
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Queries/CaseSplit.hs b/Documentation/SBV/Examples/Queries/CaseSplit.hs
--- a/Documentation/SBV/Examples/Queries/CaseSplit.hs
+++ b/Documentation/SBV/Examples/Queries/CaseSplit.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Queries.CaseSplit
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Queries/Enums.hs b/Documentation/SBV/Examples/Queries/Enums.hs
--- a/Documentation/SBV/Examples/Queries/Enums.hs
+++ b/Documentation/SBV/Examples/Queries/Enums.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Queries.Enums
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Queries/FourFours.hs b/Documentation/SBV/Examples/Queries/FourFours.hs
--- a/Documentation/SBV/Examples/Queries/FourFours.hs
+++ b/Documentation/SBV/Examples/Queries/FourFours.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Queries.FourFours
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -100,7 +100,7 @@
 
 -- | Minor helper for writing "symbolic" case statements. Simply walks down a list
 -- of values to match against a symbolic version of the key.
-sCase :: (SymVal a, Mergeable v) => SBV a -> [(a, v)] -> v
+sCase :: (Eq a, SymVal a, Mergeable v) => SBV a -> [(a, v)] -> v
 sCase k = walk
   where walk []              = error "sCase: Expected a non-empty list of cases!"
         walk [(_, v)]        = v
diff --git a/Documentation/SBV/Examples/Queries/GuessNumber.hs b/Documentation/SBV/Examples/Queries/GuessNumber.hs
--- a/Documentation/SBV/Examples/Queries/GuessNumber.hs
+++ b/Documentation/SBV/Examples/Queries/GuessNumber.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Queries.GuessNumber
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Queries/Interpolants.hs b/Documentation/SBV/Examples/Queries/Interpolants.hs
--- a/Documentation/SBV/Examples/Queries/Interpolants.hs
+++ b/Documentation/SBV/Examples/Queries/Interpolants.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Queries.Interpolants
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Queries/UnsatCore.hs b/Documentation/SBV/Examples/Queries/UnsatCore.hs
--- a/Documentation/SBV/Examples/Queries/UnsatCore.hs
+++ b/Documentation/SBV/Examples/Queries/UnsatCore.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Queries.UnsatCore
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Strings/RegexCrossword.hs b/Documentation/SBV/Examples/Strings/RegexCrossword.hs
--- a/Documentation/SBV/Examples/Strings/RegexCrossword.hs
+++ b/Documentation/SBV/Examples/Strings/RegexCrossword.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Strings.RegexCrossword
--- Author    : Joel Burget
+-- Copyright : (c) Joel Burget
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Strings/SQLInjection.hs b/Documentation/SBV/Examples/Strings/SQLInjection.hs
--- a/Documentation/SBV/Examples/Strings/SQLInjection.hs
+++ b/Documentation/SBV/Examples/Strings/SQLInjection.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Strings.SQLInjection
--- Author    : Joel Burget
+-- Copyright : (c) Joel Burget
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Transformers/SymbolicEval.hs b/Documentation/SBV/Examples/Transformers/SymbolicEval.hs
--- a/Documentation/SBV/Examples/Transformers/SymbolicEval.hs
+++ b/Documentation/SBV/Examples/Transformers/SymbolicEval.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Transformers.SymbolicEval
--- Author    : Brian Schroeder
+-- Copyright : (c) Brian Schroeder
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -30,7 +30,7 @@
 import Control.Monad.Except   (Except, ExceptT, MonadError, mapExceptT, runExceptT, throwError)
 import Control.Monad.Identity (Identity(runIdentity))
 import Control.Monad.IO.Class (MonadIO)
-import Control.Monad.Reader   (MonadReader(ask, reader), ReaderT, runReaderT)
+import Control.Monad.Reader   (MonadReader(reader), asks, ReaderT, runReaderT)
 import Control.Monad.Trans    (lift)
 
 import Data.SBV.Dynamic   (SVal)
@@ -92,8 +92,8 @@
 
 -- | Symbolic evaluation function for 'Term'.
 eval :: Term r -> Eval (SBV r)
-eval (Var "x")           = unsafeCastSBV . envX <$> ask
-eval (Var "y")           = unsafeCastSBV . envY <$> ask
+eval (Var "x")           = asks $ unsafeCastSBV . envX
+eval (Var "y")           = asks $ unsafeCastSBV . envY
 eval (Var "result")      = do mRes <- reader result
                               case mRes of
                                 Nothing -> throwError "unknown variable"
diff --git a/Documentation/SBV/Examples/Uninterpreted/AUF.hs b/Documentation/SBV/Examples/Uninterpreted/AUF.hs
--- a/Documentation/SBV/Examples/Uninterpreted/AUF.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/AUF.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Uninterpreted.AUF
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Uninterpreted/Deduce.hs b/Documentation/SBV/Examples/Uninterpreted/Deduce.hs
--- a/Documentation/SBV/Examples/Uninterpreted/Deduce.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/Deduce.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Uninterpreted.Deduce
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Uninterpreted/Function.hs b/Documentation/SBV/Examples/Uninterpreted/Function.hs
--- a/Documentation/SBV/Examples/Uninterpreted/Function.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/Function.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Uninterpreted.Function
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Uninterpreted/Multiply.hs b/Documentation/SBV/Examples/Uninterpreted/Multiply.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/Uninterpreted/Multiply.hs
@@ -0,0 +1,86 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.Uninterpreted.Multiply
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Demonstrates how to use uninterpreted function models to synthesize
+-- a simple two-bit multiplier.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module Documentation.SBV.Examples.Uninterpreted.Multiply where
+
+import Data.SBV
+
+-- | The uninterpreted implementation of our 2x2 multiplier. We simply
+-- receive two 2-bit values, and return the high and the low bit of the
+-- resulting multiplication via two uninterpreted functions that we
+-- called @mul22_hi@ and @mul22_lo@. Note that there is absolutely
+-- no computation going on here, aside from simply passing the arguments
+-- to the uninterpreted functions and stitching it back together.
+--
+-- NB. While definining @mul22_lo@ we used our domain knowledge that the
+-- low-bit of the multiplication only depends on the low bits of the inputs.
+-- However, this is merely a simplifying assumption; we could have passed
+-- all the arguments as well.
+mul22 :: (SBool, SBool) -> (SBool, SBool) -> (SBool, SBool)
+mul22 (a1, a0) (b1, b0) = (mul22_hi, mul22_lo)
+  where mul22_hi = uninterpret "mul22_hi" a1 a0 b1 b0
+        mul22_lo = uninterpret "mul22_lo"    a0    b0
+
+
+-- | Synthesize a 2x2 multiplier. We use 8-bit inputs merely because that is
+-- the lowest bit-size SBV supports but that is more or less irrelevant. (Larger
+-- sizes would work too.) We simply assert this for all input values, extract
+-- the bottom two bits, and assert that our "uninterpreted" implementation in 'mul22'
+-- is precisely the same. We have:
+--
+-- >>> sat synthMul22
+-- Satisfiable. Model:
+--   mul22_hi :: Bool -> Bool -> Bool -> Bool -> Bool
+--   mul22_hi False True  True  False = True
+--   mul22_hi False True  True  True  = True
+--   mul22_hi True  False False True  = True
+--   mul22_hi True  False True  True  = True
+--   mul22_hi True  True  False True  = True
+--   mul22_hi True  True  True  False = True
+--   mul22_hi _     _     _     _     = False
+-- <BLANKLINE>
+--   mul22_lo :: Bool -> Bool -> Bool
+--   mul22_lo True True = True
+--   mul22_lo _    _    = False
+--
+-- It is easy to see that the low bit is simply the logical-and of the low bits. It takes a moment of
+-- staring, but you can see that the high bit is correct as well: The logical formula is @a1b xor a0b1@,
+-- and if you work out the truth-table presented, you'll see that it is exactly that. Of course,
+-- you can use SBV to prove this. First, define the model we were given to make it symbolic:
+--
+-- >>> :{
+-- mul22_hi :: SBool -> SBool -> SBool -> SBool -> SBool
+-- mul22_hi a1 a0 b1 b0 = ite ([a1, a0, b1, b0] .== [sFalse, sTrue , sTrue , sFalse]) sTrue
+--                      $ ite ([a1, a0, b1, b0] .== [sFalse, sTrue , sTrue , sTrue ]) sTrue
+--                      $ ite ([a1, a0, b1, b0] .== [sTrue , sFalse, sFalse, sTrue ]) sTrue
+--                      $ ite ([a1, a0, b1, b0] .== [sTrue , sFalse, sTrue , sTrue ]) sTrue
+--                      $ ite ([a1, a0, b1, b0] .== [sTrue , sTrue , sFalse, sTrue ]) sTrue
+--                      $ ite ([a1, a0, b1, b0] .== [sTrue , sTrue , sTrue , sFalse]) sTrue
+--                        sFalse
+-- :}
+--
+-- Now we can say:
+--
+-- >>> prove $ \a1 a0 b1 b0 -> mul22_hi a1 a0 b1 b0 .== (a1 .&& b0) .<+> (a0 .&& b1)
+-- Q.E.D.
+--
+-- and rest assured that we have a correctly synthesized circuit!
+synthMul22 :: Goal
+synthMul22 = do a :: SWord8 <- forall "a"
+                b :: SWord8 <- forall "b"
+
+                let lsb2 x = let [x1, x0] = reverse $ take 2 $ blastLE x
+                             in (x1, x0)
+
+                constrain $ mul22 (lsb2 a) (lsb2 b) .== lsb2 (a * b)
diff --git a/Documentation/SBV/Examples/Uninterpreted/Shannon.hs b/Documentation/SBV/Examples/Uninterpreted/Shannon.hs
--- a/Documentation/SBV/Examples/Uninterpreted/Shannon.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/Shannon.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Uninterpreted.Shannon
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/Documentation/SBV/Examples/Uninterpreted/Sort.hs b/Documentation/SBV/Examples/Uninterpreted/Sort.hs
--- a/Documentation/SBV/Examples/Uninterpreted/Sort.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/Sort.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Uninterpreted.Sort
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -34,6 +34,9 @@
 -- >>> t1
 -- Satisfiable. Model:
 --   x = Q!val!0 :: Q
+-- <BLANKLINE>
+--   f :: Q -> Q
+--   f _ = Q!val!1
 t1 :: IO SatResult
 t1 = sat $ do x <- free "x"
               return $ f x ./= x
diff --git a/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs b/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs
--- a/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs
+++ b/Documentation/SBV/Examples/Uninterpreted/UISortAllSat.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Documentation.SBV.Examples.Uninterpreted.UISortAllSat
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -49,27 +49,41 @@
 --
 -- As expected, we have:
 --
--- >>> genLs
+-- >>> allSat genLs
 -- Solution #1:
 --   l  = L!val!0 :: L
 --   l0 = L!val!0 :: L
 --   l1 = L!val!1 :: L
 --   l2 = L!val!2 :: L
+-- <BLANKLINE>
+--   classify :: L -> Integer
+--   classify L!val!2 = 2
+--   classify L!val!1 = 1
+--   classify _       = 0
 -- Solution #2:
 --   l  = L!val!1 :: L
 --   l0 = L!val!0 :: L
 --   l1 = L!val!1 :: L
 --   l2 = L!val!2 :: L
+-- <BLANKLINE>
+--   classify :: L -> Integer
+--   classify L!val!2 = 2
+--   classify L!val!1 = 1
+--   classify _       = 0
 -- Solution #3:
 --   l  = L!val!2 :: L
 --   l0 = L!val!0 :: L
 --   l1 = L!val!1 :: L
 --   l2 = L!val!2 :: L
+-- <BLANKLINE>
+--   classify :: L -> Integer
+--   classify L!val!2 = 2
+--   classify L!val!1 = 1
+--   classify _       = 0
 -- Found 3 different solutions.
-genLs :: IO AllSatResult
-genLs = allSatWith z3
-               $ do [l, l0, l1, l2] <- symbolics ["l", "l0", "l1", "l2"]
-                    constrain $ classify l0 .== 0
-                    constrain $ classify l1 .== 1
-                    constrain $ classify l2 .== 2
-                    return $ l .== l0 .|| l .== l1 .|| l .== l2
+genLs :: Predicate
+genLs = do [l, l0, l1, l2] <- symbolics ["l", "l0", "l1", "l2"]
+           constrain $ classify l0 .== 0
+           constrain $ classify l1 .== 1
+           constrain $ classify l2 .== 2
+           return $ l .== l0 .|| l .== l1 .|| l .== l2
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/Append.hs b/Documentation/SBV/Examples/WeakestPreconditions/Append.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/WeakestPreconditions/Append.hs
@@ -0,0 +1,121 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.WeakestPreconditions.Append
+-- Copyright : Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proof of correctness of an imperative list-append algorithm, using weakest
+-- preconditions. Illustrates the use of SBV's symbolic lists together with
+-- the WP algorithm.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+{-# LANGUAGE OverloadedLists       #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Append where
+
+import Data.SBV
+import Data.SBV.Control
+
+import           Data.SBV.List ((.++))
+import qualified Data.SBV.List as L
+
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+-- * Program state
+
+-- | The state of the length program, paramaterized over the element type @a@
+data AppS a = AppS { xs :: SList a  -- ^ The first input list
+                   , ys :: SList a  -- ^ The second input list
+                   , ts :: SList a  -- ^ Temporary variable
+                   , zs :: SList a  -- ^ Output
+                   }
+                   deriving (Generic, Mergeable)
+
+-- | The concrete counterpart of 'AppS'. Again, we can't simply use the duality between
+-- @SBV a@ and @a@ due to the difference between @SList a@ and @[a]@.
+data AppC a = AppC [a] [a] [a] [a]
+
+-- | Show instance for 'AppS'. The above deriving clause would work just as well,
+-- but we want it to be a little prettier here, and hence the @OVERLAPS@ directive.
+instance {-# OVERLAPS #-} (SymVal a, Show a) => Show (AppS a) where
+  show (AppS xs ys ts zs) = "{xs = " ++ sh xs ++ ", ys = " ++ sh ys ++ ", ts = " ++ sh ts ++ ", zs = " ++ sh zs ++ "}"
+    where sh v = case unliteral v of
+                   Nothing -> "<symbolic>"
+                   Just i  -> show i
+
+-- | Show instance, a bit more prettier than what would be derived:
+instance Show a => Show (AppC a) where
+  show (AppC xs ys ts zs) = "{xs = " ++ show xs ++ ", ys = " ++ show ys ++ ", ts = " ++ show ts ++ ", zs = " ++ show zs ++ "}"
+
+-- | 'Queriable' instance for the program state
+instance Queriable IO (AppS Integer) (AppC Integer) where
+  create                     = AppS <$> freshVar_   <*> freshVar_   <*> freshVar_   <*> freshVar_
+  project (AppS xs ys ts zs) = AppC <$> getValue xs <*> getValue ys <*> getValue ts <*> getValue zs
+  embed   (AppC xs ys ts zs) = return $ AppS (literal xs) (literal ys) (literal ts) (literal zs)
+
+-- | Helper type synonym
+type A = AppS Integer
+
+-- * The algorithm
+
+-- | The imperative append algorithm:
+--
+-- @
+--    zs = []
+--    ts = xs
+--    while not (null ts)
+--      zs = zs ++ [head ts]
+--      ts = tail ts
+--    ts = ys
+--    while not (null ts)
+--      zs = zs ++ [head ts]
+--      ts = tail ts
+-- @
+algorithm :: Stmt A
+algorithm = Seq [ Assign $ \st          -> st{zs = []}
+                , Assign $ \st@AppS{xs} -> st{ts = xs}
+                , loop "xs" (\AppS{xs, zs, ts} -> xs .== zs .++ ts)
+                , Assign $ \st@AppS{ys} -> st{ts = ys}
+                , loop "ys" (\AppS{xs, ys, zs, ts} -> xs .++ ys .== zs .++ ts)
+                ]
+  where loop w inv = While ("walk over " ++ w)
+                           inv
+                           (Just (\AppS{ts} -> [L.length ts]))
+                           (\AppS{ts} -> sNot (L.null ts))
+                           $ Seq [ Assign $ \st@AppS{ts, zs} -> st{zs = zs `L.snoc` L.head ts}
+                                 , Assign $ \st@AppS{ts}     -> st{ts = L.tail ts            }
+                                 ]
+
+-- | A program is the algorithm, together with its pre- and post-conditions.
+imperativeAppend :: Program A
+imperativeAppend = Program { setup         = return ()
+                           , precondition  = const sTrue  -- no precondition
+                           , program       = algorithm
+                           , postcondition = postcondition
+                           , stability     = noChange
+                           }
+  where -- We must append properly!
+        postcondition :: A -> SBool
+        postcondition AppS{xs, ys, zs} = zs .== xs .++ ys
+
+        -- Program should never change values of @xs@ and @ys@
+        noChange = [stable "xs" xs, stable "ys" ys]
+
+-- * Correctness
+
+-- | We check that @zs@ is @xs ++ ys@ upon termination.
+--
+-- >>> correctness
+-- Total correctness is established.
+-- Q.E.D.
+correctness :: IO (ProofResult (AppC Integer))
+correctness = wpProveWith defaultWPCfg{wpVerbose=True} imperativeAppend
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/Fib.hs b/Documentation/SBV/Examples/WeakestPreconditions/Fib.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/WeakestPreconditions/Fib.hs
@@ -0,0 +1,203 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.WeakestPreconditions.Fib
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proof of correctness of an imperative fibonacci algorithm, using weakest
+-- preconditions. Note that due to the recursive nature of fibonacci, we
+-- cannot write the spec directly, so we use an uninterpreted function
+-- and proper axioms to complete the proof.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Fib where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+-- * Program state
+
+-- | The state for the sum program, parameterized over a base type @a@.
+data FibS a = FibS { n :: a    -- ^ The input value
+                   , i :: a    -- ^ Loop counter
+                   , k :: a    -- ^ tracks @fib (i+1)@
+                   , m :: a    -- ^ tracks @fib i@
+                   }
+                   deriving (Show, Generic, Mergeable, Functor, Foldable, Traversable)
+
+-- | Show instance for 'FibS'. The above deriving clause would work just as well,
+-- but we want it to be a little prettier here, and hence the @OVERLAPS@ directive.
+instance {-# OVERLAPS #-} (SymVal a, Show a) => Show (FibS (SBV a)) where
+   show (FibS n i k m) = "{n = " ++ sh n ++ ", i = " ++ sh i ++ ", k = " ++ sh k ++ ", m = " ++ sh m ++ "}"
+     where sh v = case unliteral v of
+                    Nothing -> "<symbolic>"
+                    Just l  -> show l
+
+-- | 'Fresh' instance for the program state
+instance (SymVal a, SMTValue a) => Fresh IO (FibS (SBV a)) where
+  fresh = FibS <$> freshVar_  <*> freshVar_  <*> freshVar_ <*> freshVar_
+
+-- | Helper type synonym
+type F = FibS SInteger
+
+-- * The algorithm
+
+-- | The imperative fibonacci algorithm:
+--
+-- @
+--     i = 0
+--     k = 1
+--     m = 0
+--     while i < n:
+--        m, k = k, m + k
+--        i++
+-- @
+--
+-- When the loop terminates, @m@ contains @fib(n)@.
+algorithm :: Stmt F
+algorithm = Seq [ Assign $ \st -> st{i = 0, k = 1, m = 0}
+                , assert "n >= 0" $ \FibS{n} -> n .>= 0
+                , While "i < n"
+                        (\FibS{n, i, k, m} -> i .<= n .&& k .== fib (i+1) .&& m .== fib i)
+                        (Just (\FibS{n, i} -> [n-i]))
+                        (\FibS{n, i} -> i .< n)
+                        $ Seq [ Assign $ \st@FibS{m, k} -> st{m = k, k = m + k}
+                              , Assign $ \st@FibS{i}    -> st{i = i+1}
+                              ]
+                ]
+
+-- | Symbolic fibonacci as our specification. Note that we cannot
+-- really implement the fibonacci function since it is not
+-- symbolically terminating.  So, we instead uninterpret and
+-- axiomatize it below.
+--
+-- NB. The concrete part of the definition is only used in calls to 'traceExecution'
+-- and is not needed for the proof. If you don't need to call 'traceExecution', you
+-- can simply ignore that part and directly uninterpret.
+fib :: SInteger -> SInteger
+fib x
+ | isSymbolic x = uninterpret "fib" x
+ | True         = go x
+ where go i = ite (i .== 0) 0
+            $ ite (i .== 1) 1
+            $ go (i-1) + go (i-2)
+
+-- | Constraints and axioms we need to state explicitly to tell
+-- the SMT solver about our specification for fibonacci.
+axiomatizeFib :: Symbolic ()
+axiomatizeFib = do -- Base cases.
+                   -- Note that we write these in forms of implications,
+                   -- instead of the more direct:
+                   --
+                   --    constrain $ fib 0 .== 0
+                   --    constrain $ fib 1 .== 1
+                   --
+                   -- As otherwise they would be concretely evaluated and
+                   -- would not be sent to the SMT solver!
+
+                   x <- sInteger_
+                   constrain $ x .== 0 .=> fib x .== 0
+                   constrain $ x .== 1 .=> fib x .== 1
+
+                   -- The inductive case. Unfortunately; SBV does not support
+                   -- adding quantified constraints in the query mode. So we
+                   -- have to write this axiom directly in SMT-Lib. Note also how
+                   -- carefully we've chosen this axiom to work with our proof!
+                   addAxiom "fib_n" [ "(assert (forall ((x Int))"
+                                    , "                (= (fib (+ x 2)) (+ (fib (+ x 1)) (fib x)))))"
+                                    ]
+
+-- | Precondition for our program: @n@ must be non-negative.
+pre :: F -> SBool
+pre FibS{n} = n .>= 0
+
+-- | Postcondition for our program: @m = fib n@
+post :: F -> SBool
+post FibS{n, m} = m .== fib n
+
+-- | Stability condition: Program must leave @n@ unchanged.
+noChange :: Stable F
+noChange = [stable "n" n]
+
+-- | A program is the algorithm, together with its pre- and post-conditions.
+imperativeFib :: Program F
+imperativeFib = Program { setup         = axiomatizeFib
+                        , precondition  = pre
+                        , program       = algorithm
+                        , postcondition = post
+                        , stability     = noChange
+                        }
+
+-- * Correctness
+
+-- | With the axioms in place, it is trivial to establish correctness:
+--
+-- >>> correctness
+-- Total correctness is established.
+-- Q.E.D.
+--
+-- Note that I found this proof to be quite fragile: If you do not get the algorithm right
+-- or the axioms aren't in place, z3 simply goes to an infinite loop, instead of providing
+-- counter-examples. Of course, this is to be expected with the quantifiers present.
+correctness :: IO (ProofResult (FibS Integer))
+correctness = wpProveWith defaultWPCfg{wpVerbose=True} imperativeFib
+
+-- * Concrete execution
+-- $concreteExec
+
+{- $concreteExec
+
+Example concrete run. As we mentioned in the definition for 'fib', the concrete-execution
+function cannot deal with uninterpreted functions and axioms for obvious reasons. In those
+cases we revert to the concrete definition. Here's an example run:
+
+>>> traceExecution imperativeFib $ FibS {n = 3, i = 0, k = 0, m = 0}
+*** Precondition holds, starting execution:
+  {n = 3, i = 0, k = 0, m = 0}
+===> [1.1] Assign
+  {n = 3, i = 0, k = 1, m = 0}
+===> [1.2] Conditional, taking the "then" branch
+  {n = 3, i = 0, k = 1, m = 0}
+===> [1.2.1] Skip
+  {n = 3, i = 0, k = 1, m = 0}
+===> [1.3] Loop "i < n": condition holds, executing the body
+  {n = 3, i = 0, k = 1, m = 0}
+===> [1.3.{1}.1] Assign
+  {n = 3, i = 0, k = 1, m = 1}
+===> [1.3.{1}.2] Assign
+  {n = 3, i = 1, k = 1, m = 1}
+===> [1.3] Loop "i < n": condition holds, executing the body
+  {n = 3, i = 1, k = 1, m = 1}
+===> [1.3.{2}.1] Assign
+  {n = 3, i = 1, k = 2, m = 1}
+===> [1.3.{2}.2] Assign
+  {n = 3, i = 2, k = 2, m = 1}
+===> [1.3] Loop "i < n": condition holds, executing the body
+  {n = 3, i = 2, k = 2, m = 1}
+===> [1.3.{3}.1] Assign
+  {n = 3, i = 2, k = 3, m = 2}
+===> [1.3.{3}.2] Assign
+  {n = 3, i = 3, k = 3, m = 2}
+===> [1.3] Loop "i < n": condition fails, terminating
+  {n = 3, i = 3, k = 3, m = 2}
+*** Program successfully terminated, post condition holds of the final state:
+  {n = 3, i = 3, k = 3, m = 2}
+Program terminated successfully. Final state:
+  {n = 3, i = 3, k = 3, m = 2}
+
+As expected, @fib 3@ is @2@.
+-}
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/GCD.hs b/Documentation/SBV/Examples/WeakestPreconditions/GCD.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/WeakestPreconditions/GCD.hs
@@ -0,0 +1,227 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.WeakestPreconditions.GCD
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proof of correctness of an imperative GCD (greatest-common divisor)
+-- algorithm, using weakest preconditions. The termination measure here
+-- illustrates the use of lexicographic ordering. Also, since symbolic
+-- version of GCD is not symbolically terminating, this is another
+-- example of using uninterpreted functions and axioms as one writes
+-- specifications for WP proofs.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.GCD where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+-- Access Prelude's gcd, but qualified:
+import Prelude hiding (gcd)
+import qualified Prelude as P (gcd)
+
+-- * Program state
+
+-- | The state for the sum program, parameterized over a base type @a@.
+data GCDS a = GCDS { x :: a    -- ^ First value
+                   , y :: a    -- ^ Second value
+                   , i :: a    -- ^ Copy of x to be modified
+                   , j :: a    -- ^ Copy of y to be modified
+                   }
+                   deriving (Show, Generic, Mergeable, Functor, Foldable, Traversable)
+
+-- | Show instance for 'GCDS'. The above deriving clause would work just as well,
+-- but we want it to be a little prettier here, and hence the @OVERLAPS@ directive.
+instance {-# OVERLAPS #-} (SymVal a, Show a) => Show (GCDS (SBV a)) where
+   show (GCDS x y i j) = "{x = " ++ sh x ++ ", y = " ++ sh y ++ ", i = " ++ sh i ++ ", j = " ++ sh j ++ "}"
+     where sh v = case unliteral v of
+                    Nothing -> "<symbolic>"
+                    Just l  -> show l
+
+-- | 'Fresh' instance for the program state
+instance (SymVal a, SMTValue a) => Fresh IO (GCDS (SBV a)) where
+  fresh = GCDS <$> freshVar_  <*> freshVar_  <*> freshVar_ <*> freshVar_
+
+-- | Helper type synonym
+type G = GCDS SInteger
+
+-- * The algorithm
+
+-- | The imperative GCD algorithm, assuming strictly positive @x@ and @y@:
+--
+-- @
+--    i = x
+--    j = y
+--    while i != j      -- While not equal
+--      if i > j
+--         i = i - j    -- i is greater; reduce it by j
+--      else
+--         j = j - i    -- j is greater; reduce it by i
+-- @
+--
+-- When the loop terminates, @i@ equals @j@ and contains @GCD(x, y)@.
+algorithm :: Stmt G
+algorithm = Seq [ assert "x > 0, y > 0" $ \GCDS{x, y} -> x .> 0 .&& y .> 0
+                , Assign $ \st@GCDS{x, y} -> st{i = x, j = y}
+                , While "i != j"
+                        inv
+                        (Just msr)
+                        (\GCDS{i, j} -> i ./= j)
+                        $ If (\GCDS{i, j} -> i .> j)
+                             (Assign $ \st@GCDS{i, j} -> st{i = i - j})
+                             (Assign $ \st@GCDS{i, j} -> st{j = j - i})
+                ]
+  where -- This invariant simply states that the value of the gcd remains the same
+        -- through the iterations.
+        inv GCDS{x, y, i, j} = x .> 0 .&& y .> 0 .&& i .> 0 .&& j .> 0 .&& gcd x y .== gcd i j
+
+        -- The measure can be taken as @i+j@ going down. However, we
+        -- can be more explicit and use the lexicographic nature: Notice
+        -- that in each iteration either @i@ goes down, or it stays the same
+        -- and @j@ goes down; and they never go below @0@. So we can
+        -- have the pair and use the lexicographic ordering.
+        msr GCDS{i, j} = [i, j]
+
+-- | Symbolic GCD as our specification. Note that we cannot
+-- really implement the GCD function since it is not
+-- symbolically terminating.  So, we instead uninterpret and
+-- axiomatize it below.
+--
+-- NB. The concrete part of the definition is only used in calls to 'traceExecution'
+-- and is not needed for the proof. If you don't need to call 'traceExecution', you
+-- can simply ignore that part and directly uninterpret. In that case, we simply
+-- use Prelude's version.
+gcd :: SInteger -> SInteger -> SInteger
+gcd x y
+ | Just i <- unliteral x, Just j <- unliteral y
+ = literal (P.gcd i j)
+ | True
+ = uninterpret "gcd" x y
+
+-- | Constraints and axioms we need to state explicitly to tell
+-- the SMT solver about our specification for GCD.
+axiomatizeGCD :: Symbolic ()
+axiomatizeGCD = do -- Base case. Strictly speaking, we don't really need this case
+                   -- here, but it declares the presence of gcd as an uninterpreted
+                   -- function to SBV so it gets registered as such.
+                   x <- sInteger_
+                   constrain $ gcd x x .== x
+
+                   -- Unfortunately; SBV does not support adding quantified constraints
+                   -- in the query mode. So we have to write this axiom directly in SMT-Lib.
+                   -- Note also how carefully we've chosen these axioms to work with our proof!
+                   -- Actually proving these is beyond the scope of our WP proof, but obviously
+                   -- should be done in some other system. (Note that SMT solvers will have hard
+                   -- time with the definition of GCD in general as the axiomatization requires
+                   -- quantification and definition requires recursion.)
+                   addAxiom "gcd_equal"    [ "(assert (forall ((x Int))"
+                                           , "                (=> (> x 0) (= (gcd x x) x))))"
+                                           ]
+                   addAxiom "gcd_unequal1" [ "(assert (forall ((x Int) (y Int))"
+                                           , "                (=> (and (> x 0) (> y 0)) (= (gcd (+ x y) y) (gcd x y)))))"
+                                           ]
+                   addAxiom "gcd_unequal2" [ "(assert (forall ((x Int) (y Int))"
+                                           , "                (=> (and (> x 0) (> y 0)) (= (gcd x (+ y x)) (gcd x y)))))"
+                                           ]
+
+-- | Precondition for our program: @x@ and @y@ must be strictly positive
+pre :: G -> SBool
+pre GCDS{x, y} = x .> 0 .&& y .> 0
+
+-- | Postcondition for our program: @i == j@ and @i = gcd x y@
+post :: G -> SBool
+post GCDS{x, y, i, j} = i .== j .&& i .== gcd x y
+
+-- | Stability condition: Program must leave @x@ and @y@ unchanged.
+noChange :: Stable G
+noChange = [stable "x" x, stable "y" y]
+
+-- | A program is the algorithm, together with its pre- and post-conditions.
+imperativeGCD :: Program G
+imperativeGCD = Program { setup         = axiomatizeGCD
+                        , precondition  = pre
+                        , program       = algorithm
+                        , postcondition = post
+                        , stability     = noChange
+                        }
+
+-- * Correctness
+
+-- | With the axioms in place, it is trivial to establish correctness:
+--
+-- >>> correctness
+-- Total correctness is established.
+-- Q.E.D.
+--
+-- Note that I found this proof to be quite fragile: If you do not get the algorithm right
+-- or the axioms aren't in place, z3 simply goes to an infinite loop, instead of providing
+-- counter-examples. Of course, this is to be expected with the quantifiers present.
+correctness :: IO (ProofResult (GCDS Integer))
+correctness = wpProveWith defaultWPCfg{wpVerbose=True} imperativeGCD
+
+-- * Concrete execution
+-- $concreteExec
+
+{- $concreteExec
+
+Example concrete run. As we mentioned in the definition for 'gcd', the concrete-execution
+function cannot deal with uninterpreted functions and axioms for obvious reasons. In those
+cases we revert to the concrete definition. Here's an example run:
+
+>>> traceExecution imperativeGCD $ GCDS {x = 14, y = 4, i = 0, j = 0}
+*** Precondition holds, starting execution:
+  {x = 14, y = 4, i = 0, j = 0}
+===> [1.1] Conditional, taking the "then" branch
+  {x = 14, y = 4, i = 0, j = 0}
+===> [1.1.1] Skip
+  {x = 14, y = 4, i = 0, j = 0}
+===> [1.2] Assign
+  {x = 14, y = 4, i = 14, j = 4}
+===> [1.3] Loop "i != j": condition holds, executing the body
+  {x = 14, y = 4, i = 14, j = 4}
+===> [1.3.{1}] Conditional, taking the "then" branch
+  {x = 14, y = 4, i = 14, j = 4}
+===> [1.3.{1}.1] Assign
+  {x = 14, y = 4, i = 10, j = 4}
+===> [1.3] Loop "i != j": condition holds, executing the body
+  {x = 14, y = 4, i = 10, j = 4}
+===> [1.3.{2}] Conditional, taking the "then" branch
+  {x = 14, y = 4, i = 10, j = 4}
+===> [1.3.{2}.1] Assign
+  {x = 14, y = 4, i = 6, j = 4}
+===> [1.3] Loop "i != j": condition holds, executing the body
+  {x = 14, y = 4, i = 6, j = 4}
+===> [1.3.{3}] Conditional, taking the "then" branch
+  {x = 14, y = 4, i = 6, j = 4}
+===> [1.3.{3}.1] Assign
+  {x = 14, y = 4, i = 2, j = 4}
+===> [1.3] Loop "i != j": condition holds, executing the body
+  {x = 14, y = 4, i = 2, j = 4}
+===> [1.3.{4}] Conditional, taking the "else" branch
+  {x = 14, y = 4, i = 2, j = 4}
+===> [1.3.{4}.2] Assign
+  {x = 14, y = 4, i = 2, j = 2}
+===> [1.3] Loop "i != j": condition fails, terminating
+  {x = 14, y = 4, i = 2, j = 2}
+*** Program successfully terminated, post condition holds of the final state:
+  {x = 14, y = 4, i = 2, j = 2}
+Program terminated successfully. Final state:
+  {x = 14, y = 4, i = 2, j = 2}
+
+As expected, @gcd 14 4@ is @2@.
+-}
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/IntDiv.hs b/Documentation/SBV/Examples/WeakestPreconditions/IntDiv.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/WeakestPreconditions/IntDiv.hs
@@ -0,0 +1,123 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.WeakestPreconditions.IntDiv
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proof of correctness of an imperative integer division algorithm, using
+-- weakest preconditions. The algorithm simply keeps subtracting the divisor
+-- until the desired quotient and the remainder is found.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.IntDiv where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+-- * Program state
+
+-- | The state for the division program, parameterized over a base type @a@.
+data DivS a = DivS { x :: a   -- ^ The dividend
+                   , y :: a   -- ^ The divisor
+                   , q :: a   -- ^ The quotient
+                   , r :: a   -- ^ The remainder
+                   }
+                   deriving (Show, Generic, Mergeable, Functor, Foldable, Traversable)
+
+-- | Show instance for 'DivS'. The above deriving clause would work just as well,
+-- but we want it to be a little prettier here, and hence the @OVERLAPS@ directive.
+instance {-# OVERLAPS #-} (SymVal a, Show a) => Show (DivS (SBV a)) where
+   show (DivS x y q r) = "{x = " ++ sh x ++ ", y = " ++ sh y ++ ", q = " ++ sh q ++ ", r = " ++ sh r ++ "}"
+     where sh v = case unliteral v of
+                    Nothing -> "<symbolic>"
+                    Just l  -> show l
+
+-- | 'Fresh' instance for the program state
+instance (SymVal a, SMTValue a) => Fresh IO (DivS (SBV a)) where
+  fresh = DivS <$> freshVar_  <*> freshVar_ <*> freshVar_ <*> freshVar_
+
+-- | Helper type synonym
+type D = DivS SInteger
+
+-- * The algorithm
+
+-- | The imperative division algorithm, assuming non-negative @x@ and strictly positive @y@:
+--
+-- @
+--    r = x                     -- set remainder to x
+--    q = 0                     -- set quotient  to 0
+--    while y <= r              -- while we can still subtract
+--      r = r - y                    -- reduce the remainder
+--      q = q + 1                    -- increase the quotient
+-- @
+--
+-- Note that we need to explicitly annotate each loop with its invariant and the termination
+-- measure. For convenience, we take those two as parameters for simplicity.
+algorithm :: Invariant D -> Maybe (Measure D) -> Stmt D
+algorithm inv msr = Seq [ assert "x, y >= 0" $ \DivS{x, y} -> x .>= 0 .&& y .>= 0
+                        , Assign $ \st@DivS{x} -> st{r = x, q = 0}
+                        , While "y <= r"
+                                inv
+                                msr
+                                (\DivS{y, r} -> y .<= r)
+                                $ Assign $ \st@DivS{y, q, r} -> st{r = r - y, q = q + 1}
+                        ]
+
+-- | Precondition for our program: @x@ must non-negative and @y@ must be strictly positive.
+-- Note that there is an explicit call to 'Data.SBV.Tools.WeakestPreconditions.abort' in our program to protect against this case, so
+-- if we do not have this precondition, all programs will fail.
+pre :: D -> SBool
+pre DivS{x, y} = x .>= 0 .&& y .> 0
+
+-- | Postcondition for our program: Remainder must be non-negative and less than @y@,
+-- and it must hold that @x = q*y + r@:
+post :: D -> SBool
+post DivS{x, y, q, r} = r .>= 0 .&& r .< y .&& x .== q * y + r
+
+-- | Stability: @x@ and @y@ must remain unchanged.
+noChange :: Stable D
+noChange = [stable "x" x, stable "y" y]
+
+-- | A program is the algorithm, together with its pre- and post-conditions.
+imperativeDiv :: Invariant D -> Maybe (Measure D) -> Program D
+imperativeDiv inv msr = Program { setup         = return ()
+                                , precondition  = pre
+                                , program       = algorithm inv msr
+                                , postcondition = post
+                                , stability     = noChange
+                                }
+
+-- * Correctness
+
+-- | The invariant is simply that @x = q * y + r@ holds at all times and @r@ is strictly positive.
+-- We need the @y > 0@ part of the invariant to establish the measure decreases, which is guaranteed
+-- by our precondition.
+invariant :: Invariant D
+invariant DivS{x, y, q, r} = y .> 0 .&& r .>= 0 .&& x .== q * y + r
+
+-- | The measure. In each iteration @r@ decreases, but always remains positive.
+-- Since @y@ is strictly positive, @r@ can serve as a measure for the loop.
+measure :: Measure D
+measure DivS{r} = [r]
+
+-- | Check that the program terminates and the post condition holds. We have:
+--
+-- >>> correctness
+-- Total correctness is established.
+-- Q.E.D.
+correctness :: IO ()
+correctness = print =<< wpProveWith defaultWPCfg{wpVerbose=True} (imperativeDiv invariant (Just measure))
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/IntSqrt.hs b/Documentation/SBV/Examples/WeakestPreconditions/IntSqrt.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/WeakestPreconditions/IntSqrt.hs
@@ -0,0 +1,136 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.WeakestPreconditions.IntSqrt
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proof of correctness of an imperative integer square-root algorithm, using
+-- weakest preconditions. The algorithm computes the floor of the square-root
+-- of a given non-negative integer by keeping a running some of all odd numbers
+-- starting from 1. Recall that @1+3+5+...+(2n+1) = (n+1)^2@, thus we can
+-- stop the counting when we exceed the input number.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.IntSqrt where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+import Prelude hiding (sqrt)
+
+-- * Program state
+
+-- | The state for the division program, parameterized over a base type @a@.
+data SqrtS a = SqrtS { x    :: a   -- ^ The input
+                     , sqrt :: a   -- ^ The floor of the square root
+                     , i    :: a   -- ^ Successive squares, as the sum of j's
+                     , j    :: a   -- ^ Successive odds
+                     }
+                     deriving (Show, Generic, Mergeable, Functor, Foldable, Traversable)
+
+-- | Show instance for 'SqrtS'. The above deriving clause would work just as well,
+-- but we want it to be a little prettier here, and hence the @OVERLAPS@ directive.
+instance {-# OVERLAPS #-} (SymVal a, Show a) => Show (SqrtS (SBV a)) where
+   show (SqrtS x sqrt i j) = "{x = " ++ sh x ++ ", sqrt = " ++ sh sqrt ++ ", i = " ++ sh i ++ ", j = " ++ sh j ++ "}"
+     where sh v = case unliteral v of
+                    Nothing -> "<symbolic>"
+                    Just l  -> show l
+
+-- | 'Fresh' instance for the program state
+instance (SymVal a, SMTValue a) => Fresh IO (SqrtS (SBV a)) where
+  fresh = SqrtS <$> freshVar_  <*> freshVar_ <*> freshVar_ <*> freshVar_
+
+-- | Helper type synonym
+type S = SqrtS SInteger
+
+-- * The algorithm
+
+-- | The imperative square-root algorithm, assuming non-negative @x@
+--
+-- @
+--    sqrt = 0                  -- set sqrt to 0
+--    i    = 1                  -- set i to 1, sum of j's so far
+--    j    = 1                  -- set j to be the first odd number i
+--    while i <= x              -- while the sum hasn't exceeded x yet
+--      sqrt = sqrt + 1              -- increase the sqrt
+--      j    = j + 2                 -- next odd number
+--      i    = i + j                 -- running sum of j's
+-- @
+--
+-- Note that we need to explicitly annotate each loop with its invariant and the termination
+-- measure. For convenience, we take those two as parameters for simplicity.
+algorithm :: Invariant S -> Maybe (Measure S) -> Stmt S
+algorithm inv msr = Seq [ assert "x >= 0" $ \SqrtS{x} -> x .>= 0
+                        , Assign $ \st -> st{sqrt = 0, i = 1, j = 1}
+                        , While "i <= x"
+                                inv
+                                msr
+                                (\SqrtS{x, i} -> i .<= x)
+                                $ Seq [ Assign $ \st@SqrtS{sqrt} -> st{sqrt = sqrt + 1}
+                                      , Assign $ \st@SqrtS{j}    -> st{j    = j + 2}
+                                      , Assign $ \st@SqrtS{i, j} -> st{i    = i + j}
+                                      ]
+                        ]
+
+-- | Precondition for our program: @x@ must be non-negative. Note that there is an explicit
+-- call to 'Data.SBV.Tools.WeakestPreconditions.abort' in our program to protect against this case, so if we do not have this
+-- precondition, all programs will fail.
+pre :: S -> SBool
+pre SqrtS{x} = x .>= 0
+
+-- | Postcondition for our program: The @sqrt@ squared must be less than or equal to @x@, and
+-- @sqrt+1@ squared must strictly exceed @x@.
+post :: S -> SBool
+post SqrtS{x, sqrt} = sq sqrt .<= x .&& sq (sqrt+1) .> x
+  where sq n = n * n
+
+-- | Stability condition: Program must leave @x@ unchanged.
+noChange :: Stable S
+noChange = [stable "x" x]
+
+-- | A program is the algorithm, together with its pre- and post-conditions.
+imperativeSqrt :: Invariant S -> Maybe (Measure S) -> Program S
+imperativeSqrt inv msr = Program { setup         = return ()
+                                 , precondition  = pre
+                                 , program       = algorithm inv msr
+                                 , postcondition = post
+                                 , stability     = noChange
+                                 }
+
+-- * Correctness
+
+-- | The invariant is that at each iteration of the loop @sqrt@ remains below or equal
+-- to the actual square-root, and @i@ tracks the square of the next value. We also
+-- have that @j@ is the @sqrt@'th odd value. Coming up with this invariant is not for
+-- the faint of heart, for details I would strongly recommend looking at Manna's seminal
+-- /Mathematical Theory of Computation/ book (chapter 3). The @j .> 0@ part is needed
+-- to establish the termination.
+invariant :: Invariant S
+invariant SqrtS{x, sqrt, i, j} = j .> 0 .&& sq sqrt .<= x .&& i .== sq (sqrt + 1) .&& j .== 2*sqrt + 1
+  where sq n = n * n
+
+-- | The measure. In each iteration @i@ strictly increases, thus reducing the differential @x - i@
+measure :: Measure S
+measure SqrtS{x, i} = [x - i]
+
+-- | Check that the program terminates and the post condition holds. We have:
+--
+-- >>> correctness
+-- Total correctness is established.
+-- Q.E.D.
+correctness :: IO ()
+correctness = print =<< wpProveWith defaultWPCfg{wpVerbose=True} (imperativeSqrt invariant (Just measure))
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/Length.hs b/Documentation/SBV/Examples/WeakestPreconditions/Length.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/WeakestPreconditions/Length.hs
@@ -0,0 +1,135 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.WeakestPreconditions.Length
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proof of correctness of an imperative list-length algorithm, using weakest
+-- preconditions. Illustrates the use of SBV's symbolic lists together with
+-- the WP algorithm.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Length where
+
+import Data.SBV
+import Data.SBV.Control
+
+import qualified Data.SBV.List as L
+
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+-- * Program state
+
+-- | The state of the length program, paramaterized over the element type @a@
+data LenS a = LenS { xs :: SList a  -- ^ The input list
+                   , ys :: SList a  -- ^ Copy of input
+                   , l  :: SInteger -- ^ Running length
+                   }
+                   deriving (Generic, Mergeable)
+
+-- | The concrete counterpart to 'LenS'. Note that we can no longer use the duality
+-- between @SBV a@ and @a@ as in other examples and just use one datatype for both.
+-- This is because @SList a@ and @[a]@ are fundamentally different types. This can
+-- be a bit confusing at first, but the point is that it is the list that is symbolic
+-- in case of an @SList a@, not that we have a concrete list with symbolic elements
+-- in it. Subtle difference, but it is important to keep these two separate.
+data LenC a = LenC [a] [a] Integer
+
+-- | Show instance: A simplified version of what would otherwise be generated.
+instance (SymVal a, Show a) => Show (LenS a) where
+  show (LenS xs ys l) = "{xs = " ++ sh xs ++ ", ys = " ++ sh ys ++ ", l = " ++ sh l ++ "}"
+    where sh v = case unliteral v of
+                   Nothing -> "<symbolic>"
+                   Just i  -> show i
+
+-- | Show instance: Similarly, we want to be a bit more concise here.
+instance Show a => Show (LenC a) where
+  show (LenC xs ys l) = "{xs = " ++ show xs ++ ", ys = " ++ show ys ++ ", l = " ++ show l ++ "}"
+
+-- | We have to write the bijection between 'LenS' and 'LenC' explicitly. Luckily, the
+-- definition is more or less boilerplate.
+instance Queriable IO (LenS Integer) (LenC Integer) where
+  create                 = LenS <$> freshVar_   <*> freshVar_   <*> freshVar_
+  project (LenS xs ys l) = LenC <$> getValue xs <*> getValue ys <*> getValue l
+  embed   (LenC xs ys l) = return $ LenS (literal xs) (literal ys) (literal l)
+
+-- | Helper type synonym
+type S = LenS Integer
+
+-- * The algorithm
+
+-- | The imperative length algorithm:
+--
+-- @
+--    ys = xs
+--    l  = 0
+--    while not (null ys)
+--      l  = l+1
+--      ys = tail ys
+-- @
+--
+-- Note that we need to explicitly annotate each loop with its invariant and the termination
+-- measure. For convenience, we take those two as parameters, so we can experiment later.
+algorithm :: Invariant S -> Maybe (Measure S) -> Stmt S
+algorithm inv msr = Seq [ Assign $ \st@LenS{xs} -> st{ys = xs, l = 0}
+                        , While "! (null ys)"
+                                inv
+                                msr
+                                (\LenS{ys} -> sNot (L.null ys))
+                                $ Seq [ Assign $ \st@LenS{l}  -> st{l  = l + 1  }
+                                      , Assign $ \st@LenS{ys} -> st{ys = L.tail ys}
+                                      ]
+                        ]
+
+-- | Precondition for our program. Nothing! It works for all lists.
+pre :: S -> SBool
+pre _ = sTrue
+
+-- | Postcondition for our program: @l@ must be the length of the input list.
+post :: S -> SBool
+post LenS{xs, l} = l .== L.length xs
+
+-- | Stability condition: Program must leave @xs@ unchanged.
+noChange :: Stable S
+noChange = [stable "xs" xs]
+
+-- | A program is the algorithm, together with its pre- and post-conditions.
+imperativeLength :: Invariant S -> Maybe (Measure S) -> Program S
+imperativeLength inv msr = Program { setup         = return ()
+                                   , precondition  = pre
+                                   , program       = algorithm inv msr
+                                   , postcondition = post
+                                   , stability     = noChange
+                                   }
+
+-- | The invariant simply relates the length of the input to the length of the
+-- current suffix and the length of the prefix traversed so far.
+invariant :: Invariant S
+invariant LenS{xs, ys, l} = L.length xs .== l + L.length ys
+
+-- | The measure is obviously the length of @ys@, as we peel elements off of it through the loop.
+measure :: Measure S
+measure LenS{ys} = [L.length ys]
+
+-- * Correctness
+
+-- | We check that @l@ is the length of the input list @xs@ upon termination.
+-- Note that even though this is an inductive proof, it is fairly easy to prove with our SMT based
+-- technology, which doesn't really handle induction at all!  The usual inductive proof steps are baked
+-- into the invariant establishment phase of the WP proof. We have:
+--
+-- >>> correctness
+-- Total correctness is established.
+-- Q.E.D.
+correctness :: IO ()
+correctness = print =<< wpProveWith defaultWPCfg{wpVerbose=True} (imperativeLength invariant (Just measure))
diff --git a/Documentation/SBV/Examples/WeakestPreconditions/Sum.hs b/Documentation/SBV/Examples/WeakestPreconditions/Sum.hs
new file mode 100644
--- /dev/null
+++ b/Documentation/SBV/Examples/WeakestPreconditions/Sum.hs
@@ -0,0 +1,243 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : Documentation.SBV.Examples.WeakestPreconditions.Sum
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Proof of correctness of an imperative summation algorithm, using weakest
+-- preconditions. We investigate a few different invariants and see how
+-- different versions lead to proofs and failures.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass        #-}
+{-# LANGUAGE DeriveFoldable        #-}
+{-# LANGUAGE DeriveGeneric         #-}
+{-# LANGUAGE DeriveTraversable     #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns        #-}
+
+module Documentation.SBV.Examples.WeakestPreconditions.Sum where
+
+import Data.SBV
+import Data.SBV.Control
+
+import Data.SBV.Tools.WeakestPreconditions
+
+import GHC.Generics (Generic)
+
+-- * Program state
+
+-- | The state for the sum program, parameterized over a base type @a@.
+data SumS a = SumS { n :: a    -- ^ The input value
+                   , i :: a    -- ^ Loop counter
+                   , s :: a    -- ^ Running sum
+                   }
+                   deriving (Show, Generic, Mergeable, Functor, Foldable, Traversable)
+
+-- | Show instance for 'SumS'. The above deriving clause would work just as well,
+-- but we want it to be a little prettier here, and hence the @OVERLAPS@ directive.
+instance {-# OVERLAPS #-} (SymVal a, Show a) => Show (SumS (SBV a)) where
+   show (SumS n i s) = "{n = " ++ sh n ++ ", i = " ++ sh i ++ ", s = " ++ sh s ++ "}"
+     where sh v = case unliteral v of
+                    Nothing -> "<symbolic>"
+                    Just l  -> show l
+
+-- | 'Fresh' instance for the program state
+instance (SymVal a, SMTValue a) => Fresh IO (SumS (SBV a)) where
+  fresh = SumS <$> freshVar_  <*> freshVar_  <*> freshVar_
+
+-- | Helper type synonym
+type S = SumS SInteger
+
+-- * The algorithm
+
+-- | The imperative summation algorithm:
+--
+-- @
+--    i = 0
+--    s = 0
+--    while i < n
+--      i = i+1
+--      s = s+i
+-- @
+--
+-- Note that we need to explicitly annotate each loop with its invariant and the termination
+-- measure. For convenience, we take those two as parameters, so we can experiment later.
+algorithm :: Invariant S -> Maybe (Measure S) -> Stmt S
+algorithm inv msr = Seq [ Assign $ \st -> st{i = 0, s = 0}
+                        , assert "n >= 0" $ \SumS{n} -> n .>= 0
+                        , While "i < n"
+                                inv
+                                msr
+                                (\SumS{i, n} -> i .< n)
+                                $ Seq [ Assign $ \st@SumS{i}    -> st{i = i+1}
+                                      , Assign $ \st@SumS{i, s} -> st{s = s+i}
+                                      ]
+                        ]
+
+-- | Precondition for our program: @n@ must be non-negative. Note that there is
+-- an explicit call to 'Data.SBV.Tools.WeakestPreconditions.abort' in our program to protect against this case, so
+-- if we do not have this precondition, all programs will fail.
+pre :: S -> SBool
+pre SumS{n} = n .>= 0
+
+-- | Postcondition for our program: @s@ must be the sum of all numbers up to
+-- and including @n@.
+post :: S -> SBool
+post SumS{n, s} = s .== (n * (n+1)) `sDiv` 2
+
+-- | Stability condition: Program must leave @n@ unchanged.
+noChange :: Stable S
+noChange = [stable "n" n]
+
+-- | A program is the algorithm, together with its pre- and post-conditions.
+imperativeSum :: Invariant S -> Maybe (Measure S) -> Program S
+imperativeSum inv msr = Program { setup         = return ()
+                                , precondition  = pre
+                                , program       = algorithm inv msr
+                                , postcondition = post
+                                , stability     = noChange
+                                }
+
+-- * Correctness
+
+-- | Check that the program terminates and @s@ equals @n*(n+1)/2@
+-- upon termination, i.e., the sum of all numbers upto @n@. Note
+-- that this only holds if @n >= 0@ to start with, as guaranteed
+-- by the precondition of our program.
+--
+-- The correct termination measure is @n-i@: It goes down in each
+-- iteration provided we start with @n >= 0@ and it always remains
+-- non-negative while the loop is executing. Note that we do not
+-- need a lexicographic measure in this case, hence we simply return
+-- a list of one element.
+--
+-- The correct invariant is a conjunction of two facts. First, @s@ is
+-- equivalent to the sum of numbers @0@ upto @i@.  This clearly holds at
+-- the beginning when @i = s = 0@, and is maintained in each iteration
+-- of the body. Second, it always holds that @i <= n@ as long as the
+-- loop executes, both before and after each execution of the body.
+-- When the loop terminates, it holds that @i = n@. Since the invariant says
+-- @s@ is the sum of all numbers up to but not including @i@, we
+-- conclude that @s@ is the sum of all numbers up to and including @n@,
+-- as requested.
+--
+-- Note that coming up with this invariant is neither trivial, nor easy
+-- to automate by any means. What SBV provides is a way to check that
+-- your invariant and termination measures are correct, not
+-- a means of coming up with them in the first place.
+--
+-- We have:
+--
+-- >>> :set -XNamedFieldPuns
+-- >>> let invariant SumS{n, i, s} = s .== (i*(i+1)) `sDiv` 2 .&& i .<= n
+-- >>> let measure   SumS{n, i}    = [n - i]
+-- >>> correctness invariant (Just measure)
+-- Total correctness is established.
+-- Q.E.D.
+correctness :: Invariant S -> Maybe (Measure S) -> IO (ProofResult (SumS Integer))
+correctness inv msr = wpProveWith defaultWPCfg{wpVerbose=True} (imperativeSum inv msr)
+
+-- * Example proof attempts
+--
+-- $examples
+
+{- $examples
+It is instructive to look at several proof attempts to see what can go wrong and how
+the weakest-precondition engine behaves.
+
+== Always false invariant
+
+Let's see what happens if we have an always false invariant. Clearly, this will not
+do the job, but it is instructive to see the output. For this exercise, we are only
+interested in partial correctness (to see the impact of the invariant only), so we
+will simply use 'Nothing' for the measures.
+
+>>> import Control.Monad (void)
+>>> let invariant _ = sFalse
+>>> void $ correctness invariant Nothing
+Following proof obligation failed:
+==================================
+  Invariant for loop "i < n" fails upon entry:
+    SumS {n = 0, i = 0, s = 0}
+
+When the invariant is constant false, it fails upon entry to the loop, and thus the
+proof itself fails.
+
+== Always true invariant
+
+The invariant must hold prior to entry to the loop, after the loop-body
+executes, and must be strong enough to establish the postcondition. The easiest
+thing to try would be the invariant that always returns true:
+
+>>> let invariant _ = sTrue
+>>> void $ correctness invariant Nothing
+Following proof obligation failed:
+==================================
+  Postcondition fails:
+    Start: SumS {n = 0, i = 0, s = 0}
+    End  : SumS {n = 0, i = 0, s = 1}
+
+In this case, we are told that the end state does not establish the
+post-condition. Indeed when @n=0@, we would expect @s=0@, not @s=1@.
+
+The natural question to ask is how did SBV come up with this unexpected
+state at the end of the program run? If you think about the program execution, indeed this
+state is unreachable: We know that @s@ represents the sum of all numbers up to @i@,
+so if @i=0@, we would expect @s@ to be @0@. Our invariant is clearly an overapproximation
+of the reachable space, and SBV is telling us that we need to constrain and outlaw
+the state @{n = 0, i = 0, s = 1}@. Clearly, the invariant has to state something
+about the relationship between @i@ and @s@, which we are missing in this case.
+
+== Failing to maintain the invariant
+
+What happens if we pose an invariant that the loop actually does not maintain? Here
+is an example:
+
+>>> let invariant SumS{n, i, s} = s .<= i .&& s .== (i*(i+1)) `sDiv` 2 .&& i .<= n
+>>> void $ correctness invariant Nothing
+Following proof obligation failed:
+==================================
+  Invariant for loop "i < n" is not maintaned by the body:
+    Before: SumS {n = 2, i = 1, s = 1}
+    After : SumS {n = 2, i = 2, s = 3}
+
+Here, we posed the extra incorrect invariant that @s <= i@ must be maintained, and SBV found us a reachable state that violates the invariant. The
+show /before/ state indeed satisfies @s <= i@, but the /after/ state does not. Note that the proof fails in this case not because the program
+is incorrect, but the stipulated invariant is not valid.
+
+== Having a bad measure, Part I
+
+The termination measure must always be non-negative:
+
+>>> let invariant SumS{n, i, s} = s .== (i*(i+1)) `sDiv` 2 .&& i .<= n
+>>> let measure   SumS{n, i}    = [- i]
+>>> void $ correctness invariant (Just measure)
+Following proof obligation failed:
+==================================
+  Measure for loop "i < n" is negative:
+    State  : SumS {n = 2, i = 1, s = 1}
+    Measure: -1
+
+The failure is pretty obvious in this case: Measure produces a negative value.
+
+== Having a bad measure, Part II
+
+The other way we can have a bad measure is if it fails to decrease through the loop body:
+
+>>> let invariant SumS{n, i, s} = s .== (i*(i+1)) `sDiv` 2 .&& i .<= n
+>>> let measure   SumS{n, i}    = [n + i]
+>>> void $ correctness invariant (Just measure)
+Following proof obligation failed:
+==================================
+  Measure for loop "i < n" does not decrease:
+    Before : SumS {n = 2, i = 1, s = 1}
+    Measure: 3
+    After  : SumS {n = 2, i = 2, s = 3}
+    Measure: 4
+
+Clearly, as @i@ increases, so does our bogus measure @n+i@.
+-}
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -7,10 +7,10 @@
 ### Build Status
 
  - Linux:
-     - GHC 8.2.2 [![Build1][3]][1]
-     - GHC 8.4.3 [![Build1][4]][1]
+     - GHC 8.4.4 [![Build1][3]][1]
+     - GHC 8.6.3 [![Build1][4]][1]
  - Mac OSX:
-     - GHC 8.4.4 [![Build1][5]][1]
+     - GHC 8.6.3 [![Build1][5]][1]
  - Windows:
      - GHC 8.6.2 [![Build5][6]][2]
 
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word16.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0010)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_left 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_left 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_left 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x0010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s13))
+[GOOD] (assert (= (table0 #x0002) s21))
+[GOOD] (assert (= (table0 #x0003) s22))
+[GOOD] (assert (= (table0 #x0004) s23))
+[GOOD] (assert (= (table0 #x0005) s24))
+[GOOD] (assert (= (table0 #x0006) s25))
+[GOOD] (assert (= (table0 #x0007) s26))
+[GOOD] (assert (= (table0 #x0008) s27))
+[GOOD] (assert (= (table0 #x0009) s28))
+[GOOD] (assert (= (table0 #x000a) s29))
+[GOOD] (assert (= (table0 #x000b) s30))
+[GOOD] (assert (= (table0 #x000c) s31))
+[GOOD] (assert (= (table0 #x000d) s32))
+[GOOD] (assert (= (table0 #x000e) s33))
+[GOOD] (assert (= (table0 #x000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word32.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000010)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_left 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_left 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_left 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x00000010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s13))
+[GOOD] (assert (= (table0 #x00000002) s21))
+[GOOD] (assert (= (table0 #x00000003) s22))
+[GOOD] (assert (= (table0 #x00000004) s23))
+[GOOD] (assert (= (table0 #x00000005) s24))
+[GOOD] (assert (= (table0 #x00000006) s25))
+[GOOD] (assert (= (table0 #x00000007) s26))
+[GOOD] (assert (= (table0 #x00000008) s27))
+[GOOD] (assert (= (table0 #x00000009) s28))
+[GOOD] (assert (= (table0 #x0000000a) s29))
+[GOOD] (assert (= (table0 #x0000000b) s30))
+[GOOD] (assert (= (table0 #x0000000c) s31))
+[GOOD] (assert (= (table0 #x0000000d) s32))
+[GOOD] (assert (= (table0 #x0000000e) s33))
+[GOOD] (assert (= (table0 #x0000000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word64.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000010)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_left 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_left 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_left 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x0000000000000010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s13))
+[GOOD] (assert (= (table0 #x0000000000000002) s21))
+[GOOD] (assert (= (table0 #x0000000000000003) s22))
+[GOOD] (assert (= (table0 #x0000000000000004) s23))
+[GOOD] (assert (= (table0 #x0000000000000005) s24))
+[GOOD] (assert (= (table0 #x0000000000000006) s25))
+[GOOD] (assert (= (table0 #x0000000000000007) s26))
+[GOOD] (assert (= (table0 #x0000000000000008) s27))
+[GOOD] (assert (= (table0 #x0000000000000009) s28))
+[GOOD] (assert (= (table0 #x000000000000000a) s29))
+[GOOD] (assert (= (table0 #x000000000000000b) s30))
+[GOOD] (assert (= (table0 #x000000000000000c) s31))
+[GOOD] (assert (= (table0 #x000000000000000d) s32))
+[GOOD] (assert (= (table0 #x000000000000000e) s33))
+[GOOD] (assert (= (table0 #x000000000000000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int16_Word8.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_left 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_left 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_left 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x10 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s13))
+[GOOD] (assert (= (table0 #x02) s21))
+[GOOD] (assert (= (table0 #x03) s22))
+[GOOD] (assert (= (table0 #x04) s23))
+[GOOD] (assert (= (table0 #x05) s24))
+[GOOD] (assert (= (table0 #x06) s25))
+[GOOD] (assert (= (table0 #x07) s26))
+[GOOD] (assert (= (table0 #x08) s27))
+[GOOD] (assert (= (table0 #x09) s28))
+[GOOD] (assert (= (table0 #x0a) s29))
+[GOOD] (assert (= (table0 #x0b) s30))
+[GOOD] (assert (= (table0 #x0c) s31))
+[GOOD] (assert (= (table0 #x0d) s32))
+[GOOD] (assert (= (table0 #x0e) s33))
+[GOOD] (assert (= (table0 #x0f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word16.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_left 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_left 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_left 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_left 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x0020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s15))
+[GOOD] (assert (= (table0 #x0002) s25))
+[GOOD] (assert (= (table0 #x0003) s26))
+[GOOD] (assert (= (table0 #x0004) s27))
+[GOOD] (assert (= (table0 #x0005) s28))
+[GOOD] (assert (= (table0 #x0006) s29))
+[GOOD] (assert (= (table0 #x0007) s30))
+[GOOD] (assert (= (table0 #x0008) s31))
+[GOOD] (assert (= (table0 #x0009) s32))
+[GOOD] (assert (= (table0 #x000a) s33))
+[GOOD] (assert (= (table0 #x000b) s34))
+[GOOD] (assert (= (table0 #x000c) s35))
+[GOOD] (assert (= (table0 #x000d) s36))
+[GOOD] (assert (= (table0 #x000e) s37))
+[GOOD] (assert (= (table0 #x000f) s38))
+[GOOD] (assert (= (table0 #x0010) s39))
+[GOOD] (assert (= (table0 #x0011) s40))
+[GOOD] (assert (= (table0 #x0012) s41))
+[GOOD] (assert (= (table0 #x0013) s42))
+[GOOD] (assert (= (table0 #x0014) s43))
+[GOOD] (assert (= (table0 #x0015) s44))
+[GOOD] (assert (= (table0 #x0016) s45))
+[GOOD] (assert (= (table0 #x0017) s46))
+[GOOD] (assert (= (table0 #x0018) s47))
+[GOOD] (assert (= (table0 #x0019) s48))
+[GOOD] (assert (= (table0 #x001a) s49))
+[GOOD] (assert (= (table0 #x001b) s50))
+[GOOD] (assert (= (table0 #x001c) s51))
+[GOOD] (assert (= (table0 #x001d) s52))
+[GOOD] (assert (= (table0 #x001e) s53))
+[GOOD] (assert (= (table0 #x001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word32.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_left 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_left 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_left 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_left 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x00000020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s15))
+[GOOD] (assert (= (table0 #x00000002) s25))
+[GOOD] (assert (= (table0 #x00000003) s26))
+[GOOD] (assert (= (table0 #x00000004) s27))
+[GOOD] (assert (= (table0 #x00000005) s28))
+[GOOD] (assert (= (table0 #x00000006) s29))
+[GOOD] (assert (= (table0 #x00000007) s30))
+[GOOD] (assert (= (table0 #x00000008) s31))
+[GOOD] (assert (= (table0 #x00000009) s32))
+[GOOD] (assert (= (table0 #x0000000a) s33))
+[GOOD] (assert (= (table0 #x0000000b) s34))
+[GOOD] (assert (= (table0 #x0000000c) s35))
+[GOOD] (assert (= (table0 #x0000000d) s36))
+[GOOD] (assert (= (table0 #x0000000e) s37))
+[GOOD] (assert (= (table0 #x0000000f) s38))
+[GOOD] (assert (= (table0 #x00000010) s39))
+[GOOD] (assert (= (table0 #x00000011) s40))
+[GOOD] (assert (= (table0 #x00000012) s41))
+[GOOD] (assert (= (table0 #x00000013) s42))
+[GOOD] (assert (= (table0 #x00000014) s43))
+[GOOD] (assert (= (table0 #x00000015) s44))
+[GOOD] (assert (= (table0 #x00000016) s45))
+[GOOD] (assert (= (table0 #x00000017) s46))
+[GOOD] (assert (= (table0 #x00000018) s47))
+[GOOD] (assert (= (table0 #x00000019) s48))
+[GOOD] (assert (= (table0 #x0000001a) s49))
+[GOOD] (assert (= (table0 #x0000001b) s50))
+[GOOD] (assert (= (table0 #x0000001c) s51))
+[GOOD] (assert (= (table0 #x0000001d) s52))
+[GOOD] (assert (= (table0 #x0000001e) s53))
+[GOOD] (assert (= (table0 #x0000001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word64.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_left 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_left 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_left 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_left 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x0000000000000020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s15))
+[GOOD] (assert (= (table0 #x0000000000000002) s25))
+[GOOD] (assert (= (table0 #x0000000000000003) s26))
+[GOOD] (assert (= (table0 #x0000000000000004) s27))
+[GOOD] (assert (= (table0 #x0000000000000005) s28))
+[GOOD] (assert (= (table0 #x0000000000000006) s29))
+[GOOD] (assert (= (table0 #x0000000000000007) s30))
+[GOOD] (assert (= (table0 #x0000000000000008) s31))
+[GOOD] (assert (= (table0 #x0000000000000009) s32))
+[GOOD] (assert (= (table0 #x000000000000000a) s33))
+[GOOD] (assert (= (table0 #x000000000000000b) s34))
+[GOOD] (assert (= (table0 #x000000000000000c) s35))
+[GOOD] (assert (= (table0 #x000000000000000d) s36))
+[GOOD] (assert (= (table0 #x000000000000000e) s37))
+[GOOD] (assert (= (table0 #x000000000000000f) s38))
+[GOOD] (assert (= (table0 #x0000000000000010) s39))
+[GOOD] (assert (= (table0 #x0000000000000011) s40))
+[GOOD] (assert (= (table0 #x0000000000000012) s41))
+[GOOD] (assert (= (table0 #x0000000000000013) s42))
+[GOOD] (assert (= (table0 #x0000000000000014) s43))
+[GOOD] (assert (= (table0 #x0000000000000015) s44))
+[GOOD] (assert (= (table0 #x0000000000000016) s45))
+[GOOD] (assert (= (table0 #x0000000000000017) s46))
+[GOOD] (assert (= (table0 #x0000000000000018) s47))
+[GOOD] (assert (= (table0 #x0000000000000019) s48))
+[GOOD] (assert (= (table0 #x000000000000001a) s49))
+[GOOD] (assert (= (table0 #x000000000000001b) s50))
+[GOOD] (assert (= (table0 #x000000000000001c) s51))
+[GOOD] (assert (= (table0 #x000000000000001d) s52))
+[GOOD] (assert (= (table0 #x000000000000001e) s53))
+[GOOD] (assert (= (table0 #x000000000000001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int32_Word8.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_left 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_left 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_left 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_left 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x20 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s15))
+[GOOD] (assert (= (table0 #x02) s25))
+[GOOD] (assert (= (table0 #x03) s26))
+[GOOD] (assert (= (table0 #x04) s27))
+[GOOD] (assert (= (table0 #x05) s28))
+[GOOD] (assert (= (table0 #x06) s29))
+[GOOD] (assert (= (table0 #x07) s30))
+[GOOD] (assert (= (table0 #x08) s31))
+[GOOD] (assert (= (table0 #x09) s32))
+[GOOD] (assert (= (table0 #x0a) s33))
+[GOOD] (assert (= (table0 #x0b) s34))
+[GOOD] (assert (= (table0 #x0c) s35))
+[GOOD] (assert (= (table0 #x0d) s36))
+[GOOD] (assert (= (table0 #x0e) s37))
+[GOOD] (assert (= (table0 #x0f) s38))
+[GOOD] (assert (= (table0 #x10) s39))
+[GOOD] (assert (= (table0 #x11) s40))
+[GOOD] (assert (= (table0 #x12) s41))
+[GOOD] (assert (= (table0 #x13) s42))
+[GOOD] (assert (= (table0 #x14) s43))
+[GOOD] (assert (= (table0 #x15) s44))
+[GOOD] (assert (= (table0 #x16) s45))
+[GOOD] (assert (= (table0 #x17) s46))
+[GOOD] (assert (= (table0 #x18) s47))
+[GOOD] (assert (= (table0 #x19) s48))
+[GOOD] (assert (= (table0 #x1a) s49))
+[GOOD] (assert (= (table0 #x1b) s50))
+[GOOD] (assert (= (table0 #x1c) s51))
+[GOOD] (assert (= (table0 #x1d) s52))
+[GOOD] (assert (= (table0 #x1e) s53))
+[GOOD] (assert (= (table0 #x1f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word16.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_left 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_left 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_left 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_left 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_left 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_left 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_left 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_left 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_left 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_left 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_left 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_left 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_left 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_left 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_left 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_left 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_left 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_left 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_left 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_left 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_left 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_left 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_left 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_left 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_left 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_left 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_left 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_left 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_left 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_left 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_left 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_left 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_left 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_left 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_left 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_left 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_left 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x0040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s17))
+[GOOD] (assert (= (table0 #x0002) s29))
+[GOOD] (assert (= (table0 #x0003) s30))
+[GOOD] (assert (= (table0 #x0004) s31))
+[GOOD] (assert (= (table0 #x0005) s32))
+[GOOD] (assert (= (table0 #x0006) s33))
+[GOOD] (assert (= (table0 #x0007) s34))
+[GOOD] (assert (= (table0 #x0008) s35))
+[GOOD] (assert (= (table0 #x0009) s36))
+[GOOD] (assert (= (table0 #x000a) s37))
+[GOOD] (assert (= (table0 #x000b) s38))
+[GOOD] (assert (= (table0 #x000c) s39))
+[GOOD] (assert (= (table0 #x000d) s40))
+[GOOD] (assert (= (table0 #x000e) s41))
+[GOOD] (assert (= (table0 #x000f) s42))
+[GOOD] (assert (= (table0 #x0010) s43))
+[GOOD] (assert (= (table0 #x0011) s44))
+[GOOD] (assert (= (table0 #x0012) s45))
+[GOOD] (assert (= (table0 #x0013) s46))
+[GOOD] (assert (= (table0 #x0014) s47))
+[GOOD] (assert (= (table0 #x0015) s48))
+[GOOD] (assert (= (table0 #x0016) s49))
+[GOOD] (assert (= (table0 #x0017) s50))
+[GOOD] (assert (= (table0 #x0018) s51))
+[GOOD] (assert (= (table0 #x0019) s52))
+[GOOD] (assert (= (table0 #x001a) s53))
+[GOOD] (assert (= (table0 #x001b) s54))
+[GOOD] (assert (= (table0 #x001c) s55))
+[GOOD] (assert (= (table0 #x001d) s56))
+[GOOD] (assert (= (table0 #x001e) s57))
+[GOOD] (assert (= (table0 #x001f) s58))
+[GOOD] (assert (= (table0 #x0020) s59))
+[GOOD] (assert (= (table0 #x0021) s60))
+[GOOD] (assert (= (table0 #x0022) s61))
+[GOOD] (assert (= (table0 #x0023) s62))
+[GOOD] (assert (= (table0 #x0024) s63))
+[GOOD] (assert (= (table0 #x0025) s64))
+[GOOD] (assert (= (table0 #x0026) s65))
+[GOOD] (assert (= (table0 #x0027) s66))
+[GOOD] (assert (= (table0 #x0028) s67))
+[GOOD] (assert (= (table0 #x0029) s68))
+[GOOD] (assert (= (table0 #x002a) s69))
+[GOOD] (assert (= (table0 #x002b) s70))
+[GOOD] (assert (= (table0 #x002c) s71))
+[GOOD] (assert (= (table0 #x002d) s72))
+[GOOD] (assert (= (table0 #x002e) s73))
+[GOOD] (assert (= (table0 #x002f) s74))
+[GOOD] (assert (= (table0 #x0030) s75))
+[GOOD] (assert (= (table0 #x0031) s76))
+[GOOD] (assert (= (table0 #x0032) s77))
+[GOOD] (assert (= (table0 #x0033) s78))
+[GOOD] (assert (= (table0 #x0034) s79))
+[GOOD] (assert (= (table0 #x0035) s80))
+[GOOD] (assert (= (table0 #x0036) s81))
+[GOOD] (assert (= (table0 #x0037) s82))
+[GOOD] (assert (= (table0 #x0038) s83))
+[GOOD] (assert (= (table0 #x0039) s84))
+[GOOD] (assert (= (table0 #x003a) s85))
+[GOOD] (assert (= (table0 #x003b) s86))
+[GOOD] (assert (= (table0 #x003c) s87))
+[GOOD] (assert (= (table0 #x003d) s88))
+[GOOD] (assert (= (table0 #x003e) s89))
+[GOOD] (assert (= (table0 #x003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word32.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_left 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_left 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_left 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_left 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_left 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_left 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_left 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_left 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_left 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_left 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_left 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_left 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_left 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_left 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_left 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_left 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_left 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_left 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_left 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_left 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_left 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_left 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_left 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_left 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_left 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_left 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_left 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_left 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_left 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_left 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_left 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_left 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_left 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_left 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_left 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_left 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_left 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x00000040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s17))
+[GOOD] (assert (= (table0 #x00000002) s29))
+[GOOD] (assert (= (table0 #x00000003) s30))
+[GOOD] (assert (= (table0 #x00000004) s31))
+[GOOD] (assert (= (table0 #x00000005) s32))
+[GOOD] (assert (= (table0 #x00000006) s33))
+[GOOD] (assert (= (table0 #x00000007) s34))
+[GOOD] (assert (= (table0 #x00000008) s35))
+[GOOD] (assert (= (table0 #x00000009) s36))
+[GOOD] (assert (= (table0 #x0000000a) s37))
+[GOOD] (assert (= (table0 #x0000000b) s38))
+[GOOD] (assert (= (table0 #x0000000c) s39))
+[GOOD] (assert (= (table0 #x0000000d) s40))
+[GOOD] (assert (= (table0 #x0000000e) s41))
+[GOOD] (assert (= (table0 #x0000000f) s42))
+[GOOD] (assert (= (table0 #x00000010) s43))
+[GOOD] (assert (= (table0 #x00000011) s44))
+[GOOD] (assert (= (table0 #x00000012) s45))
+[GOOD] (assert (= (table0 #x00000013) s46))
+[GOOD] (assert (= (table0 #x00000014) s47))
+[GOOD] (assert (= (table0 #x00000015) s48))
+[GOOD] (assert (= (table0 #x00000016) s49))
+[GOOD] (assert (= (table0 #x00000017) s50))
+[GOOD] (assert (= (table0 #x00000018) s51))
+[GOOD] (assert (= (table0 #x00000019) s52))
+[GOOD] (assert (= (table0 #x0000001a) s53))
+[GOOD] (assert (= (table0 #x0000001b) s54))
+[GOOD] (assert (= (table0 #x0000001c) s55))
+[GOOD] (assert (= (table0 #x0000001d) s56))
+[GOOD] (assert (= (table0 #x0000001e) s57))
+[GOOD] (assert (= (table0 #x0000001f) s58))
+[GOOD] (assert (= (table0 #x00000020) s59))
+[GOOD] (assert (= (table0 #x00000021) s60))
+[GOOD] (assert (= (table0 #x00000022) s61))
+[GOOD] (assert (= (table0 #x00000023) s62))
+[GOOD] (assert (= (table0 #x00000024) s63))
+[GOOD] (assert (= (table0 #x00000025) s64))
+[GOOD] (assert (= (table0 #x00000026) s65))
+[GOOD] (assert (= (table0 #x00000027) s66))
+[GOOD] (assert (= (table0 #x00000028) s67))
+[GOOD] (assert (= (table0 #x00000029) s68))
+[GOOD] (assert (= (table0 #x0000002a) s69))
+[GOOD] (assert (= (table0 #x0000002b) s70))
+[GOOD] (assert (= (table0 #x0000002c) s71))
+[GOOD] (assert (= (table0 #x0000002d) s72))
+[GOOD] (assert (= (table0 #x0000002e) s73))
+[GOOD] (assert (= (table0 #x0000002f) s74))
+[GOOD] (assert (= (table0 #x00000030) s75))
+[GOOD] (assert (= (table0 #x00000031) s76))
+[GOOD] (assert (= (table0 #x00000032) s77))
+[GOOD] (assert (= (table0 #x00000033) s78))
+[GOOD] (assert (= (table0 #x00000034) s79))
+[GOOD] (assert (= (table0 #x00000035) s80))
+[GOOD] (assert (= (table0 #x00000036) s81))
+[GOOD] (assert (= (table0 #x00000037) s82))
+[GOOD] (assert (= (table0 #x00000038) s83))
+[GOOD] (assert (= (table0 #x00000039) s84))
+[GOOD] (assert (= (table0 #x0000003a) s85))
+[GOOD] (assert (= (table0 #x0000003b) s86))
+[GOOD] (assert (= (table0 #x0000003c) s87))
+[GOOD] (assert (= (table0 #x0000003d) s88))
+[GOOD] (assert (= (table0 #x0000003e) s89))
+[GOOD] (assert (= (table0 #x0000003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word64.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_left 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_left 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_left 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_left 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_left 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_left 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_left 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_left 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_left 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_left 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_left 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_left 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_left 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_left 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_left 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_left 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_left 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_left 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_left 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_left 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_left 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_left 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_left 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_left 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_left 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_left 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_left 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_left 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_left 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_left 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_left 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_left 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_left 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_left 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_left 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_left 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_left 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x0000000000000040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s17))
+[GOOD] (assert (= (table0 #x0000000000000002) s29))
+[GOOD] (assert (= (table0 #x0000000000000003) s30))
+[GOOD] (assert (= (table0 #x0000000000000004) s31))
+[GOOD] (assert (= (table0 #x0000000000000005) s32))
+[GOOD] (assert (= (table0 #x0000000000000006) s33))
+[GOOD] (assert (= (table0 #x0000000000000007) s34))
+[GOOD] (assert (= (table0 #x0000000000000008) s35))
+[GOOD] (assert (= (table0 #x0000000000000009) s36))
+[GOOD] (assert (= (table0 #x000000000000000a) s37))
+[GOOD] (assert (= (table0 #x000000000000000b) s38))
+[GOOD] (assert (= (table0 #x000000000000000c) s39))
+[GOOD] (assert (= (table0 #x000000000000000d) s40))
+[GOOD] (assert (= (table0 #x000000000000000e) s41))
+[GOOD] (assert (= (table0 #x000000000000000f) s42))
+[GOOD] (assert (= (table0 #x0000000000000010) s43))
+[GOOD] (assert (= (table0 #x0000000000000011) s44))
+[GOOD] (assert (= (table0 #x0000000000000012) s45))
+[GOOD] (assert (= (table0 #x0000000000000013) s46))
+[GOOD] (assert (= (table0 #x0000000000000014) s47))
+[GOOD] (assert (= (table0 #x0000000000000015) s48))
+[GOOD] (assert (= (table0 #x0000000000000016) s49))
+[GOOD] (assert (= (table0 #x0000000000000017) s50))
+[GOOD] (assert (= (table0 #x0000000000000018) s51))
+[GOOD] (assert (= (table0 #x0000000000000019) s52))
+[GOOD] (assert (= (table0 #x000000000000001a) s53))
+[GOOD] (assert (= (table0 #x000000000000001b) s54))
+[GOOD] (assert (= (table0 #x000000000000001c) s55))
+[GOOD] (assert (= (table0 #x000000000000001d) s56))
+[GOOD] (assert (= (table0 #x000000000000001e) s57))
+[GOOD] (assert (= (table0 #x000000000000001f) s58))
+[GOOD] (assert (= (table0 #x0000000000000020) s59))
+[GOOD] (assert (= (table0 #x0000000000000021) s60))
+[GOOD] (assert (= (table0 #x0000000000000022) s61))
+[GOOD] (assert (= (table0 #x0000000000000023) s62))
+[GOOD] (assert (= (table0 #x0000000000000024) s63))
+[GOOD] (assert (= (table0 #x0000000000000025) s64))
+[GOOD] (assert (= (table0 #x0000000000000026) s65))
+[GOOD] (assert (= (table0 #x0000000000000027) s66))
+[GOOD] (assert (= (table0 #x0000000000000028) s67))
+[GOOD] (assert (= (table0 #x0000000000000029) s68))
+[GOOD] (assert (= (table0 #x000000000000002a) s69))
+[GOOD] (assert (= (table0 #x000000000000002b) s70))
+[GOOD] (assert (= (table0 #x000000000000002c) s71))
+[GOOD] (assert (= (table0 #x000000000000002d) s72))
+[GOOD] (assert (= (table0 #x000000000000002e) s73))
+[GOOD] (assert (= (table0 #x000000000000002f) s74))
+[GOOD] (assert (= (table0 #x0000000000000030) s75))
+[GOOD] (assert (= (table0 #x0000000000000031) s76))
+[GOOD] (assert (= (table0 #x0000000000000032) s77))
+[GOOD] (assert (= (table0 #x0000000000000033) s78))
+[GOOD] (assert (= (table0 #x0000000000000034) s79))
+[GOOD] (assert (= (table0 #x0000000000000035) s80))
+[GOOD] (assert (= (table0 #x0000000000000036) s81))
+[GOOD] (assert (= (table0 #x0000000000000037) s82))
+[GOOD] (assert (= (table0 #x0000000000000038) s83))
+[GOOD] (assert (= (table0 #x0000000000000039) s84))
+[GOOD] (assert (= (table0 #x000000000000003a) s85))
+[GOOD] (assert (= (table0 #x000000000000003b) s86))
+[GOOD] (assert (= (table0 #x000000000000003c) s87))
+[GOOD] (assert (= (table0 #x000000000000003d) s88))
+[GOOD] (assert (= (table0 #x000000000000003e) s89))
+[GOOD] (assert (= (table0 #x000000000000003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int64_Word8.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_left 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_left 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_left 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_left 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_left 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_left 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_left 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_left 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_left 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_left 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_left 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_left 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_left 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_left 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_left 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_left 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_left 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_left 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_left 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_left 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_left 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_left 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_left 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_left 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_left 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_left 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_left 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_left 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_left 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_left 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_left 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_left 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_left 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_left 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_left 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_left 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_left 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x40 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s17))
+[GOOD] (assert (= (table0 #x02) s29))
+[GOOD] (assert (= (table0 #x03) s30))
+[GOOD] (assert (= (table0 #x04) s31))
+[GOOD] (assert (= (table0 #x05) s32))
+[GOOD] (assert (= (table0 #x06) s33))
+[GOOD] (assert (= (table0 #x07) s34))
+[GOOD] (assert (= (table0 #x08) s35))
+[GOOD] (assert (= (table0 #x09) s36))
+[GOOD] (assert (= (table0 #x0a) s37))
+[GOOD] (assert (= (table0 #x0b) s38))
+[GOOD] (assert (= (table0 #x0c) s39))
+[GOOD] (assert (= (table0 #x0d) s40))
+[GOOD] (assert (= (table0 #x0e) s41))
+[GOOD] (assert (= (table0 #x0f) s42))
+[GOOD] (assert (= (table0 #x10) s43))
+[GOOD] (assert (= (table0 #x11) s44))
+[GOOD] (assert (= (table0 #x12) s45))
+[GOOD] (assert (= (table0 #x13) s46))
+[GOOD] (assert (= (table0 #x14) s47))
+[GOOD] (assert (= (table0 #x15) s48))
+[GOOD] (assert (= (table0 #x16) s49))
+[GOOD] (assert (= (table0 #x17) s50))
+[GOOD] (assert (= (table0 #x18) s51))
+[GOOD] (assert (= (table0 #x19) s52))
+[GOOD] (assert (= (table0 #x1a) s53))
+[GOOD] (assert (= (table0 #x1b) s54))
+[GOOD] (assert (= (table0 #x1c) s55))
+[GOOD] (assert (= (table0 #x1d) s56))
+[GOOD] (assert (= (table0 #x1e) s57))
+[GOOD] (assert (= (table0 #x1f) s58))
+[GOOD] (assert (= (table0 #x20) s59))
+[GOOD] (assert (= (table0 #x21) s60))
+[GOOD] (assert (= (table0 #x22) s61))
+[GOOD] (assert (= (table0 #x23) s62))
+[GOOD] (assert (= (table0 #x24) s63))
+[GOOD] (assert (= (table0 #x25) s64))
+[GOOD] (assert (= (table0 #x26) s65))
+[GOOD] (assert (= (table0 #x27) s66))
+[GOOD] (assert (= (table0 #x28) s67))
+[GOOD] (assert (= (table0 #x29) s68))
+[GOOD] (assert (= (table0 #x2a) s69))
+[GOOD] (assert (= (table0 #x2b) s70))
+[GOOD] (assert (= (table0 #x2c) s71))
+[GOOD] (assert (= (table0 #x2d) s72))
+[GOOD] (assert (= (table0 #x2e) s73))
+[GOOD] (assert (= (table0 #x2f) s74))
+[GOOD] (assert (= (table0 #x30) s75))
+[GOOD] (assert (= (table0 #x31) s76))
+[GOOD] (assert (= (table0 #x32) s77))
+[GOOD] (assert (= (table0 #x33) s78))
+[GOOD] (assert (= (table0 #x34) s79))
+[GOOD] (assert (= (table0 #x35) s80))
+[GOOD] (assert (= (table0 #x36) s81))
+[GOOD] (assert (= (table0 #x37) s82))
+[GOOD] (assert (= (table0 #x38) s83))
+[GOOD] (assert (= (table0 #x39) s84))
+[GOOD] (assert (= (table0 #x3a) s85))
+[GOOD] (assert (= (table0 #x3b) s86))
+[GOOD] (assert (= (table0 #x3c) s87))
+[GOOD] (assert (= (table0 #x3d) s88))
+[GOOD] (assert (= (table0 #x3e) s89))
+[GOOD] (assert (= (table0 #x3f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word16.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0008)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_left 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_left 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x0008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s11))
+[GOOD] (assert (= (table0 #x0002) s17))
+[GOOD] (assert (= (table0 #x0003) s18))
+[GOOD] (assert (= (table0 #x0004) s19))
+[GOOD] (assert (= (table0 #x0005) s20))
+[GOOD] (assert (= (table0 #x0006) s21))
+[GOOD] (assert (= (table0 #x0007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word32.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000008)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_left 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_left 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x00000008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s11))
+[GOOD] (assert (= (table0 #x00000002) s17))
+[GOOD] (assert (= (table0 #x00000003) s18))
+[GOOD] (assert (= (table0 #x00000004) s19))
+[GOOD] (assert (= (table0 #x00000005) s20))
+[GOOD] (assert (= (table0 #x00000006) s21))
+[GOOD] (assert (= (table0 #x00000007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word64.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000008)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_left 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_left 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x0000000000000008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s11))
+[GOOD] (assert (= (table0 #x0000000000000002) s17))
+[GOOD] (assert (= (table0 #x0000000000000003) s18))
+[GOOD] (assert (= (table0 #x0000000000000004) s19))
+[GOOD] (assert (= (table0 #x0000000000000005) s20))
+[GOOD] (assert (= (table0 #x0000000000000006) s21))
+[GOOD] (assert (= (table0 #x0000000000000007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Int8_Word8.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_left 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_left 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x08 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s11))
+[GOOD] (assert (= (table0 #x02) s17))
+[GOOD] (assert (= (table0 #x03) s18))
+[GOOD] (assert (= (table0 #x04) s19))
+[GOOD] (assert (= (table0 #x05) s20))
+[GOOD] (assert (= (table0 #x06) s21))
+[GOOD] (assert (= (table0 #x07) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word16.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0010)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_left 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_left 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_left 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x0010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s13))
+[GOOD] (assert (= (table0 #x0002) s21))
+[GOOD] (assert (= (table0 #x0003) s22))
+[GOOD] (assert (= (table0 #x0004) s23))
+[GOOD] (assert (= (table0 #x0005) s24))
+[GOOD] (assert (= (table0 #x0006) s25))
+[GOOD] (assert (= (table0 #x0007) s26))
+[GOOD] (assert (= (table0 #x0008) s27))
+[GOOD] (assert (= (table0 #x0009) s28))
+[GOOD] (assert (= (table0 #x000a) s29))
+[GOOD] (assert (= (table0 #x000b) s30))
+[GOOD] (assert (= (table0 #x000c) s31))
+[GOOD] (assert (= (table0 #x000d) s32))
+[GOOD] (assert (= (table0 #x000e) s33))
+[GOOD] (assert (= (table0 #x000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word32.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000010)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_left 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_left 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_left 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x00000010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s13))
+[GOOD] (assert (= (table0 #x00000002) s21))
+[GOOD] (assert (= (table0 #x00000003) s22))
+[GOOD] (assert (= (table0 #x00000004) s23))
+[GOOD] (assert (= (table0 #x00000005) s24))
+[GOOD] (assert (= (table0 #x00000006) s25))
+[GOOD] (assert (= (table0 #x00000007) s26))
+[GOOD] (assert (= (table0 #x00000008) s27))
+[GOOD] (assert (= (table0 #x00000009) s28))
+[GOOD] (assert (= (table0 #x0000000a) s29))
+[GOOD] (assert (= (table0 #x0000000b) s30))
+[GOOD] (assert (= (table0 #x0000000c) s31))
+[GOOD] (assert (= (table0 #x0000000d) s32))
+[GOOD] (assert (= (table0 #x0000000e) s33))
+[GOOD] (assert (= (table0 #x0000000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word64.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000010)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_left 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_left 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_left 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x0000000000000010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s13))
+[GOOD] (assert (= (table0 #x0000000000000002) s21))
+[GOOD] (assert (= (table0 #x0000000000000003) s22))
+[GOOD] (assert (= (table0 #x0000000000000004) s23))
+[GOOD] (assert (= (table0 #x0000000000000005) s24))
+[GOOD] (assert (= (table0 #x0000000000000006) s25))
+[GOOD] (assert (= (table0 #x0000000000000007) s26))
+[GOOD] (assert (= (table0 #x0000000000000008) s27))
+[GOOD] (assert (= (table0 #x0000000000000009) s28))
+[GOOD] (assert (= (table0 #x000000000000000a) s29))
+[GOOD] (assert (= (table0 #x000000000000000b) s30))
+[GOOD] (assert (= (table0 #x000000000000000c) s31))
+[GOOD] (assert (= (table0 #x000000000000000d) s32))
+[GOOD] (assert (= (table0 #x000000000000000e) s33))
+[GOOD] (assert (= (table0 #x000000000000000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word16_Word8.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_left 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_left 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_left 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x10 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s13))
+[GOOD] (assert (= (table0 #x02) s21))
+[GOOD] (assert (= (table0 #x03) s22))
+[GOOD] (assert (= (table0 #x04) s23))
+[GOOD] (assert (= (table0 #x05) s24))
+[GOOD] (assert (= (table0 #x06) s25))
+[GOOD] (assert (= (table0 #x07) s26))
+[GOOD] (assert (= (table0 #x08) s27))
+[GOOD] (assert (= (table0 #x09) s28))
+[GOOD] (assert (= (table0 #x0a) s29))
+[GOOD] (assert (= (table0 #x0b) s30))
+[GOOD] (assert (= (table0 #x0c) s31))
+[GOOD] (assert (= (table0 #x0d) s32))
+[GOOD] (assert (= (table0 #x0e) s33))
+[GOOD] (assert (= (table0 #x0f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word16.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_left 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_left 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_left 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_left 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x0020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s15))
+[GOOD] (assert (= (table0 #x0002) s25))
+[GOOD] (assert (= (table0 #x0003) s26))
+[GOOD] (assert (= (table0 #x0004) s27))
+[GOOD] (assert (= (table0 #x0005) s28))
+[GOOD] (assert (= (table0 #x0006) s29))
+[GOOD] (assert (= (table0 #x0007) s30))
+[GOOD] (assert (= (table0 #x0008) s31))
+[GOOD] (assert (= (table0 #x0009) s32))
+[GOOD] (assert (= (table0 #x000a) s33))
+[GOOD] (assert (= (table0 #x000b) s34))
+[GOOD] (assert (= (table0 #x000c) s35))
+[GOOD] (assert (= (table0 #x000d) s36))
+[GOOD] (assert (= (table0 #x000e) s37))
+[GOOD] (assert (= (table0 #x000f) s38))
+[GOOD] (assert (= (table0 #x0010) s39))
+[GOOD] (assert (= (table0 #x0011) s40))
+[GOOD] (assert (= (table0 #x0012) s41))
+[GOOD] (assert (= (table0 #x0013) s42))
+[GOOD] (assert (= (table0 #x0014) s43))
+[GOOD] (assert (= (table0 #x0015) s44))
+[GOOD] (assert (= (table0 #x0016) s45))
+[GOOD] (assert (= (table0 #x0017) s46))
+[GOOD] (assert (= (table0 #x0018) s47))
+[GOOD] (assert (= (table0 #x0019) s48))
+[GOOD] (assert (= (table0 #x001a) s49))
+[GOOD] (assert (= (table0 #x001b) s50))
+[GOOD] (assert (= (table0 #x001c) s51))
+[GOOD] (assert (= (table0 #x001d) s52))
+[GOOD] (assert (= (table0 #x001e) s53))
+[GOOD] (assert (= (table0 #x001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word32.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_left 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_left 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_left 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_left 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x00000020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s15))
+[GOOD] (assert (= (table0 #x00000002) s25))
+[GOOD] (assert (= (table0 #x00000003) s26))
+[GOOD] (assert (= (table0 #x00000004) s27))
+[GOOD] (assert (= (table0 #x00000005) s28))
+[GOOD] (assert (= (table0 #x00000006) s29))
+[GOOD] (assert (= (table0 #x00000007) s30))
+[GOOD] (assert (= (table0 #x00000008) s31))
+[GOOD] (assert (= (table0 #x00000009) s32))
+[GOOD] (assert (= (table0 #x0000000a) s33))
+[GOOD] (assert (= (table0 #x0000000b) s34))
+[GOOD] (assert (= (table0 #x0000000c) s35))
+[GOOD] (assert (= (table0 #x0000000d) s36))
+[GOOD] (assert (= (table0 #x0000000e) s37))
+[GOOD] (assert (= (table0 #x0000000f) s38))
+[GOOD] (assert (= (table0 #x00000010) s39))
+[GOOD] (assert (= (table0 #x00000011) s40))
+[GOOD] (assert (= (table0 #x00000012) s41))
+[GOOD] (assert (= (table0 #x00000013) s42))
+[GOOD] (assert (= (table0 #x00000014) s43))
+[GOOD] (assert (= (table0 #x00000015) s44))
+[GOOD] (assert (= (table0 #x00000016) s45))
+[GOOD] (assert (= (table0 #x00000017) s46))
+[GOOD] (assert (= (table0 #x00000018) s47))
+[GOOD] (assert (= (table0 #x00000019) s48))
+[GOOD] (assert (= (table0 #x0000001a) s49))
+[GOOD] (assert (= (table0 #x0000001b) s50))
+[GOOD] (assert (= (table0 #x0000001c) s51))
+[GOOD] (assert (= (table0 #x0000001d) s52))
+[GOOD] (assert (= (table0 #x0000001e) s53))
+[GOOD] (assert (= (table0 #x0000001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word64.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000020)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_left 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_left 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_left 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_left 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x0000000000000020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s15))
+[GOOD] (assert (= (table0 #x0000000000000002) s25))
+[GOOD] (assert (= (table0 #x0000000000000003) s26))
+[GOOD] (assert (= (table0 #x0000000000000004) s27))
+[GOOD] (assert (= (table0 #x0000000000000005) s28))
+[GOOD] (assert (= (table0 #x0000000000000006) s29))
+[GOOD] (assert (= (table0 #x0000000000000007) s30))
+[GOOD] (assert (= (table0 #x0000000000000008) s31))
+[GOOD] (assert (= (table0 #x0000000000000009) s32))
+[GOOD] (assert (= (table0 #x000000000000000a) s33))
+[GOOD] (assert (= (table0 #x000000000000000b) s34))
+[GOOD] (assert (= (table0 #x000000000000000c) s35))
+[GOOD] (assert (= (table0 #x000000000000000d) s36))
+[GOOD] (assert (= (table0 #x000000000000000e) s37))
+[GOOD] (assert (= (table0 #x000000000000000f) s38))
+[GOOD] (assert (= (table0 #x0000000000000010) s39))
+[GOOD] (assert (= (table0 #x0000000000000011) s40))
+[GOOD] (assert (= (table0 #x0000000000000012) s41))
+[GOOD] (assert (= (table0 #x0000000000000013) s42))
+[GOOD] (assert (= (table0 #x0000000000000014) s43))
+[GOOD] (assert (= (table0 #x0000000000000015) s44))
+[GOOD] (assert (= (table0 #x0000000000000016) s45))
+[GOOD] (assert (= (table0 #x0000000000000017) s46))
+[GOOD] (assert (= (table0 #x0000000000000018) s47))
+[GOOD] (assert (= (table0 #x0000000000000019) s48))
+[GOOD] (assert (= (table0 #x000000000000001a) s49))
+[GOOD] (assert (= (table0 #x000000000000001b) s50))
+[GOOD] (assert (= (table0 #x000000000000001c) s51))
+[GOOD] (assert (= (table0 #x000000000000001d) s52))
+[GOOD] (assert (= (table0 #x000000000000001e) s53))
+[GOOD] (assert (= (table0 #x000000000000001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word32_Word8.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_left 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_left 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_left 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_left 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x20 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s15))
+[GOOD] (assert (= (table0 #x02) s25))
+[GOOD] (assert (= (table0 #x03) s26))
+[GOOD] (assert (= (table0 #x04) s27))
+[GOOD] (assert (= (table0 #x05) s28))
+[GOOD] (assert (= (table0 #x06) s29))
+[GOOD] (assert (= (table0 #x07) s30))
+[GOOD] (assert (= (table0 #x08) s31))
+[GOOD] (assert (= (table0 #x09) s32))
+[GOOD] (assert (= (table0 #x0a) s33))
+[GOOD] (assert (= (table0 #x0b) s34))
+[GOOD] (assert (= (table0 #x0c) s35))
+[GOOD] (assert (= (table0 #x0d) s36))
+[GOOD] (assert (= (table0 #x0e) s37))
+[GOOD] (assert (= (table0 #x0f) s38))
+[GOOD] (assert (= (table0 #x10) s39))
+[GOOD] (assert (= (table0 #x11) s40))
+[GOOD] (assert (= (table0 #x12) s41))
+[GOOD] (assert (= (table0 #x13) s42))
+[GOOD] (assert (= (table0 #x14) s43))
+[GOOD] (assert (= (table0 #x15) s44))
+[GOOD] (assert (= (table0 #x16) s45))
+[GOOD] (assert (= (table0 #x17) s46))
+[GOOD] (assert (= (table0 #x18) s47))
+[GOOD] (assert (= (table0 #x19) s48))
+[GOOD] (assert (= (table0 #x1a) s49))
+[GOOD] (assert (= (table0 #x1b) s50))
+[GOOD] (assert (= (table0 #x1c) s51))
+[GOOD] (assert (= (table0 #x1d) s52))
+[GOOD] (assert (= (table0 #x1e) s53))
+[GOOD] (assert (= (table0 #x1f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word16.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_left 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_left 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_left 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_left 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_left 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_left 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_left 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_left 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_left 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_left 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_left 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_left 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_left 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_left 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_left 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_left 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_left 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_left 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_left 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_left 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_left 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_left 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_left 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_left 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_left 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_left 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_left 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_left 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_left 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_left 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_left 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_left 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_left 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_left 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_left 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_left 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_left 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x0040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s17))
+[GOOD] (assert (= (table0 #x0002) s29))
+[GOOD] (assert (= (table0 #x0003) s30))
+[GOOD] (assert (= (table0 #x0004) s31))
+[GOOD] (assert (= (table0 #x0005) s32))
+[GOOD] (assert (= (table0 #x0006) s33))
+[GOOD] (assert (= (table0 #x0007) s34))
+[GOOD] (assert (= (table0 #x0008) s35))
+[GOOD] (assert (= (table0 #x0009) s36))
+[GOOD] (assert (= (table0 #x000a) s37))
+[GOOD] (assert (= (table0 #x000b) s38))
+[GOOD] (assert (= (table0 #x000c) s39))
+[GOOD] (assert (= (table0 #x000d) s40))
+[GOOD] (assert (= (table0 #x000e) s41))
+[GOOD] (assert (= (table0 #x000f) s42))
+[GOOD] (assert (= (table0 #x0010) s43))
+[GOOD] (assert (= (table0 #x0011) s44))
+[GOOD] (assert (= (table0 #x0012) s45))
+[GOOD] (assert (= (table0 #x0013) s46))
+[GOOD] (assert (= (table0 #x0014) s47))
+[GOOD] (assert (= (table0 #x0015) s48))
+[GOOD] (assert (= (table0 #x0016) s49))
+[GOOD] (assert (= (table0 #x0017) s50))
+[GOOD] (assert (= (table0 #x0018) s51))
+[GOOD] (assert (= (table0 #x0019) s52))
+[GOOD] (assert (= (table0 #x001a) s53))
+[GOOD] (assert (= (table0 #x001b) s54))
+[GOOD] (assert (= (table0 #x001c) s55))
+[GOOD] (assert (= (table0 #x001d) s56))
+[GOOD] (assert (= (table0 #x001e) s57))
+[GOOD] (assert (= (table0 #x001f) s58))
+[GOOD] (assert (= (table0 #x0020) s59))
+[GOOD] (assert (= (table0 #x0021) s60))
+[GOOD] (assert (= (table0 #x0022) s61))
+[GOOD] (assert (= (table0 #x0023) s62))
+[GOOD] (assert (= (table0 #x0024) s63))
+[GOOD] (assert (= (table0 #x0025) s64))
+[GOOD] (assert (= (table0 #x0026) s65))
+[GOOD] (assert (= (table0 #x0027) s66))
+[GOOD] (assert (= (table0 #x0028) s67))
+[GOOD] (assert (= (table0 #x0029) s68))
+[GOOD] (assert (= (table0 #x002a) s69))
+[GOOD] (assert (= (table0 #x002b) s70))
+[GOOD] (assert (= (table0 #x002c) s71))
+[GOOD] (assert (= (table0 #x002d) s72))
+[GOOD] (assert (= (table0 #x002e) s73))
+[GOOD] (assert (= (table0 #x002f) s74))
+[GOOD] (assert (= (table0 #x0030) s75))
+[GOOD] (assert (= (table0 #x0031) s76))
+[GOOD] (assert (= (table0 #x0032) s77))
+[GOOD] (assert (= (table0 #x0033) s78))
+[GOOD] (assert (= (table0 #x0034) s79))
+[GOOD] (assert (= (table0 #x0035) s80))
+[GOOD] (assert (= (table0 #x0036) s81))
+[GOOD] (assert (= (table0 #x0037) s82))
+[GOOD] (assert (= (table0 #x0038) s83))
+[GOOD] (assert (= (table0 #x0039) s84))
+[GOOD] (assert (= (table0 #x003a) s85))
+[GOOD] (assert (= (table0 #x003b) s86))
+[GOOD] (assert (= (table0 #x003c) s87))
+[GOOD] (assert (= (table0 #x003d) s88))
+[GOOD] (assert (= (table0 #x003e) s89))
+[GOOD] (assert (= (table0 #x003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word32.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_left 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_left 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_left 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_left 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_left 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_left 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_left 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_left 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_left 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_left 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_left 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_left 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_left 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_left 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_left 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_left 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_left 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_left 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_left 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_left 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_left 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_left 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_left 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_left 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_left 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_left 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_left 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_left 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_left 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_left 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_left 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_left 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_left 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_left 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_left 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_left 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_left 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x00000040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s17))
+[GOOD] (assert (= (table0 #x00000002) s29))
+[GOOD] (assert (= (table0 #x00000003) s30))
+[GOOD] (assert (= (table0 #x00000004) s31))
+[GOOD] (assert (= (table0 #x00000005) s32))
+[GOOD] (assert (= (table0 #x00000006) s33))
+[GOOD] (assert (= (table0 #x00000007) s34))
+[GOOD] (assert (= (table0 #x00000008) s35))
+[GOOD] (assert (= (table0 #x00000009) s36))
+[GOOD] (assert (= (table0 #x0000000a) s37))
+[GOOD] (assert (= (table0 #x0000000b) s38))
+[GOOD] (assert (= (table0 #x0000000c) s39))
+[GOOD] (assert (= (table0 #x0000000d) s40))
+[GOOD] (assert (= (table0 #x0000000e) s41))
+[GOOD] (assert (= (table0 #x0000000f) s42))
+[GOOD] (assert (= (table0 #x00000010) s43))
+[GOOD] (assert (= (table0 #x00000011) s44))
+[GOOD] (assert (= (table0 #x00000012) s45))
+[GOOD] (assert (= (table0 #x00000013) s46))
+[GOOD] (assert (= (table0 #x00000014) s47))
+[GOOD] (assert (= (table0 #x00000015) s48))
+[GOOD] (assert (= (table0 #x00000016) s49))
+[GOOD] (assert (= (table0 #x00000017) s50))
+[GOOD] (assert (= (table0 #x00000018) s51))
+[GOOD] (assert (= (table0 #x00000019) s52))
+[GOOD] (assert (= (table0 #x0000001a) s53))
+[GOOD] (assert (= (table0 #x0000001b) s54))
+[GOOD] (assert (= (table0 #x0000001c) s55))
+[GOOD] (assert (= (table0 #x0000001d) s56))
+[GOOD] (assert (= (table0 #x0000001e) s57))
+[GOOD] (assert (= (table0 #x0000001f) s58))
+[GOOD] (assert (= (table0 #x00000020) s59))
+[GOOD] (assert (= (table0 #x00000021) s60))
+[GOOD] (assert (= (table0 #x00000022) s61))
+[GOOD] (assert (= (table0 #x00000023) s62))
+[GOOD] (assert (= (table0 #x00000024) s63))
+[GOOD] (assert (= (table0 #x00000025) s64))
+[GOOD] (assert (= (table0 #x00000026) s65))
+[GOOD] (assert (= (table0 #x00000027) s66))
+[GOOD] (assert (= (table0 #x00000028) s67))
+[GOOD] (assert (= (table0 #x00000029) s68))
+[GOOD] (assert (= (table0 #x0000002a) s69))
+[GOOD] (assert (= (table0 #x0000002b) s70))
+[GOOD] (assert (= (table0 #x0000002c) s71))
+[GOOD] (assert (= (table0 #x0000002d) s72))
+[GOOD] (assert (= (table0 #x0000002e) s73))
+[GOOD] (assert (= (table0 #x0000002f) s74))
+[GOOD] (assert (= (table0 #x00000030) s75))
+[GOOD] (assert (= (table0 #x00000031) s76))
+[GOOD] (assert (= (table0 #x00000032) s77))
+[GOOD] (assert (= (table0 #x00000033) s78))
+[GOOD] (assert (= (table0 #x00000034) s79))
+[GOOD] (assert (= (table0 #x00000035) s80))
+[GOOD] (assert (= (table0 #x00000036) s81))
+[GOOD] (assert (= (table0 #x00000037) s82))
+[GOOD] (assert (= (table0 #x00000038) s83))
+[GOOD] (assert (= (table0 #x00000039) s84))
+[GOOD] (assert (= (table0 #x0000003a) s85))
+[GOOD] (assert (= (table0 #x0000003b) s86))
+[GOOD] (assert (= (table0 #x0000003c) s87))
+[GOOD] (assert (= (table0 #x0000003d) s88))
+[GOOD] (assert (= (table0 #x0000003e) s89))
+[GOOD] (assert (= (table0 #x0000003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word64.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_left 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_left 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_left 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_left 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_left 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_left 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_left 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_left 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_left 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_left 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_left 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_left 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_left 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_left 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_left 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_left 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_left 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_left 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_left 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_left 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_left 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_left 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_left 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_left 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_left 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_left 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_left 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_left 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_left 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_left 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_left 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_left 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_left 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_left 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_left 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_left 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_left 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x0000000000000040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s17))
+[GOOD] (assert (= (table0 #x0000000000000002) s29))
+[GOOD] (assert (= (table0 #x0000000000000003) s30))
+[GOOD] (assert (= (table0 #x0000000000000004) s31))
+[GOOD] (assert (= (table0 #x0000000000000005) s32))
+[GOOD] (assert (= (table0 #x0000000000000006) s33))
+[GOOD] (assert (= (table0 #x0000000000000007) s34))
+[GOOD] (assert (= (table0 #x0000000000000008) s35))
+[GOOD] (assert (= (table0 #x0000000000000009) s36))
+[GOOD] (assert (= (table0 #x000000000000000a) s37))
+[GOOD] (assert (= (table0 #x000000000000000b) s38))
+[GOOD] (assert (= (table0 #x000000000000000c) s39))
+[GOOD] (assert (= (table0 #x000000000000000d) s40))
+[GOOD] (assert (= (table0 #x000000000000000e) s41))
+[GOOD] (assert (= (table0 #x000000000000000f) s42))
+[GOOD] (assert (= (table0 #x0000000000000010) s43))
+[GOOD] (assert (= (table0 #x0000000000000011) s44))
+[GOOD] (assert (= (table0 #x0000000000000012) s45))
+[GOOD] (assert (= (table0 #x0000000000000013) s46))
+[GOOD] (assert (= (table0 #x0000000000000014) s47))
+[GOOD] (assert (= (table0 #x0000000000000015) s48))
+[GOOD] (assert (= (table0 #x0000000000000016) s49))
+[GOOD] (assert (= (table0 #x0000000000000017) s50))
+[GOOD] (assert (= (table0 #x0000000000000018) s51))
+[GOOD] (assert (= (table0 #x0000000000000019) s52))
+[GOOD] (assert (= (table0 #x000000000000001a) s53))
+[GOOD] (assert (= (table0 #x000000000000001b) s54))
+[GOOD] (assert (= (table0 #x000000000000001c) s55))
+[GOOD] (assert (= (table0 #x000000000000001d) s56))
+[GOOD] (assert (= (table0 #x000000000000001e) s57))
+[GOOD] (assert (= (table0 #x000000000000001f) s58))
+[GOOD] (assert (= (table0 #x0000000000000020) s59))
+[GOOD] (assert (= (table0 #x0000000000000021) s60))
+[GOOD] (assert (= (table0 #x0000000000000022) s61))
+[GOOD] (assert (= (table0 #x0000000000000023) s62))
+[GOOD] (assert (= (table0 #x0000000000000024) s63))
+[GOOD] (assert (= (table0 #x0000000000000025) s64))
+[GOOD] (assert (= (table0 #x0000000000000026) s65))
+[GOOD] (assert (= (table0 #x0000000000000027) s66))
+[GOOD] (assert (= (table0 #x0000000000000028) s67))
+[GOOD] (assert (= (table0 #x0000000000000029) s68))
+[GOOD] (assert (= (table0 #x000000000000002a) s69))
+[GOOD] (assert (= (table0 #x000000000000002b) s70))
+[GOOD] (assert (= (table0 #x000000000000002c) s71))
+[GOOD] (assert (= (table0 #x000000000000002d) s72))
+[GOOD] (assert (= (table0 #x000000000000002e) s73))
+[GOOD] (assert (= (table0 #x000000000000002f) s74))
+[GOOD] (assert (= (table0 #x0000000000000030) s75))
+[GOOD] (assert (= (table0 #x0000000000000031) s76))
+[GOOD] (assert (= (table0 #x0000000000000032) s77))
+[GOOD] (assert (= (table0 #x0000000000000033) s78))
+[GOOD] (assert (= (table0 #x0000000000000034) s79))
+[GOOD] (assert (= (table0 #x0000000000000035) s80))
+[GOOD] (assert (= (table0 #x0000000000000036) s81))
+[GOOD] (assert (= (table0 #x0000000000000037) s82))
+[GOOD] (assert (= (table0 #x0000000000000038) s83))
+[GOOD] (assert (= (table0 #x0000000000000039) s84))
+[GOOD] (assert (= (table0 #x000000000000003a) s85))
+[GOOD] (assert (= (table0 #x000000000000003b) s86))
+[GOOD] (assert (= (table0 #x000000000000003c) s87))
+[GOOD] (assert (= (table0 #x000000000000003d) s88))
+[GOOD] (assert (= (table0 #x000000000000003e) s89))
+[GOOD] (assert (= (table0 #x000000000000003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word64_Word8.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_left 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_left 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_left 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_left 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_left 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_left 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_left 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_left 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_left 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_left 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_left 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_left 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_left 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_left 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_left 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_left 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_left 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_left 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_left 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_left 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_left 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_left 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_left 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_left 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_left 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_left 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_left 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_left 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_left 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_left 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_left 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_left 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_left 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_left 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_left 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_left 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_left 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_left 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_left 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_left 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_left 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_left 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_left 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_left 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_left 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_left 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_left 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_left 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_left 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_left 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_left 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_left 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_left 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_left 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_left 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_left 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_left 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_left 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_left 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_left 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_left 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x40 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s17))
+[GOOD] (assert (= (table0 #x02) s29))
+[GOOD] (assert (= (table0 #x03) s30))
+[GOOD] (assert (= (table0 #x04) s31))
+[GOOD] (assert (= (table0 #x05) s32))
+[GOOD] (assert (= (table0 #x06) s33))
+[GOOD] (assert (= (table0 #x07) s34))
+[GOOD] (assert (= (table0 #x08) s35))
+[GOOD] (assert (= (table0 #x09) s36))
+[GOOD] (assert (= (table0 #x0a) s37))
+[GOOD] (assert (= (table0 #x0b) s38))
+[GOOD] (assert (= (table0 #x0c) s39))
+[GOOD] (assert (= (table0 #x0d) s40))
+[GOOD] (assert (= (table0 #x0e) s41))
+[GOOD] (assert (= (table0 #x0f) s42))
+[GOOD] (assert (= (table0 #x10) s43))
+[GOOD] (assert (= (table0 #x11) s44))
+[GOOD] (assert (= (table0 #x12) s45))
+[GOOD] (assert (= (table0 #x13) s46))
+[GOOD] (assert (= (table0 #x14) s47))
+[GOOD] (assert (= (table0 #x15) s48))
+[GOOD] (assert (= (table0 #x16) s49))
+[GOOD] (assert (= (table0 #x17) s50))
+[GOOD] (assert (= (table0 #x18) s51))
+[GOOD] (assert (= (table0 #x19) s52))
+[GOOD] (assert (= (table0 #x1a) s53))
+[GOOD] (assert (= (table0 #x1b) s54))
+[GOOD] (assert (= (table0 #x1c) s55))
+[GOOD] (assert (= (table0 #x1d) s56))
+[GOOD] (assert (= (table0 #x1e) s57))
+[GOOD] (assert (= (table0 #x1f) s58))
+[GOOD] (assert (= (table0 #x20) s59))
+[GOOD] (assert (= (table0 #x21) s60))
+[GOOD] (assert (= (table0 #x22) s61))
+[GOOD] (assert (= (table0 #x23) s62))
+[GOOD] (assert (= (table0 #x24) s63))
+[GOOD] (assert (= (table0 #x25) s64))
+[GOOD] (assert (= (table0 #x26) s65))
+[GOOD] (assert (= (table0 #x27) s66))
+[GOOD] (assert (= (table0 #x28) s67))
+[GOOD] (assert (= (table0 #x29) s68))
+[GOOD] (assert (= (table0 #x2a) s69))
+[GOOD] (assert (= (table0 #x2b) s70))
+[GOOD] (assert (= (table0 #x2c) s71))
+[GOOD] (assert (= (table0 #x2d) s72))
+[GOOD] (assert (= (table0 #x2e) s73))
+[GOOD] (assert (= (table0 #x2f) s74))
+[GOOD] (assert (= (table0 #x30) s75))
+[GOOD] (assert (= (table0 #x31) s76))
+[GOOD] (assert (= (table0 #x32) s77))
+[GOOD] (assert (= (table0 #x33) s78))
+[GOOD] (assert (= (table0 #x34) s79))
+[GOOD] (assert (= (table0 #x35) s80))
+[GOOD] (assert (= (table0 #x36) s81))
+[GOOD] (assert (= (table0 #x37) s82))
+[GOOD] (assert (= (table0 #x38) s83))
+[GOOD] (assert (= (table0 #x39) s84))
+[GOOD] (assert (= (table0 #x3a) s85))
+[GOOD] (assert (= (table0 #x3b) s86))
+[GOOD] (assert (= (table0 #x3c) s87))
+[GOOD] (assert (= (table0 #x3d) s88))
+[GOOD] (assert (= (table0 #x3e) s89))
+[GOOD] (assert (= (table0 #x3f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word16.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0008)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_left 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_left 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x0008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s11))
+[GOOD] (assert (= (table0 #x0002) s17))
+[GOOD] (assert (= (table0 #x0003) s18))
+[GOOD] (assert (= (table0 #x0004) s19))
+[GOOD] (assert (= (table0 #x0005) s20))
+[GOOD] (assert (= (table0 #x0006) s21))
+[GOOD] (assert (= (table0 #x0007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word32.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000008)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_left 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_left 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x00000008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s11))
+[GOOD] (assert (= (table0 #x00000002) s17))
+[GOOD] (assert (= (table0 #x00000003) s18))
+[GOOD] (assert (= (table0 #x00000004) s19))
+[GOOD] (assert (= (table0 #x00000005) s20))
+[GOOD] (assert (= (table0 #x00000006) s21))
+[GOOD] (assert (= (table0 #x00000007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word64.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000008)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_left 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_left 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x0000000000000008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s11))
+[GOOD] (assert (= (table0 #x0000000000000002) s17))
+[GOOD] (assert (= (table0 #x0000000000000003) s18))
+[GOOD] (assert (= (table0 #x0000000000000004) s19))
+[GOOD] (assert (= (table0 #x0000000000000005) s20))
+[GOOD] (assert (= (table0 #x0000000000000006) s21))
+[GOOD] (assert (= (table0 #x0000000000000007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Left_Word8_Word8.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_left 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_left 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_left 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_left 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_left 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_left 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_left 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_left 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_left 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x08 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s11))
+[GOOD] (assert (= (table0 #x02) s17))
+[GOOD] (assert (= (table0 #x03) s18))
+[GOOD] (assert (= (table0 #x04) s19))
+[GOOD] (assert (= (table0 #x05) s20))
+[GOOD] (assert (= (table0 #x06) s21))
+[GOOD] (assert (= (table0 #x07) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word16.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0010)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_right 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_right 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_right 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x0010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s13))
+[GOOD] (assert (= (table0 #x0002) s21))
+[GOOD] (assert (= (table0 #x0003) s22))
+[GOOD] (assert (= (table0 #x0004) s23))
+[GOOD] (assert (= (table0 #x0005) s24))
+[GOOD] (assert (= (table0 #x0006) s25))
+[GOOD] (assert (= (table0 #x0007) s26))
+[GOOD] (assert (= (table0 #x0008) s27))
+[GOOD] (assert (= (table0 #x0009) s28))
+[GOOD] (assert (= (table0 #x000a) s29))
+[GOOD] (assert (= (table0 #x000b) s30))
+[GOOD] (assert (= (table0 #x000c) s31))
+[GOOD] (assert (= (table0 #x000d) s32))
+[GOOD] (assert (= (table0 #x000e) s33))
+[GOOD] (assert (= (table0 #x000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word32.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000010)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_right 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_right 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_right 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x00000010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s13))
+[GOOD] (assert (= (table0 #x00000002) s21))
+[GOOD] (assert (= (table0 #x00000003) s22))
+[GOOD] (assert (= (table0 #x00000004) s23))
+[GOOD] (assert (= (table0 #x00000005) s24))
+[GOOD] (assert (= (table0 #x00000006) s25))
+[GOOD] (assert (= (table0 #x00000007) s26))
+[GOOD] (assert (= (table0 #x00000008) s27))
+[GOOD] (assert (= (table0 #x00000009) s28))
+[GOOD] (assert (= (table0 #x0000000a) s29))
+[GOOD] (assert (= (table0 #x0000000b) s30))
+[GOOD] (assert (= (table0 #x0000000c) s31))
+[GOOD] (assert (= (table0 #x0000000d) s32))
+[GOOD] (assert (= (table0 #x0000000e) s33))
+[GOOD] (assert (= (table0 #x0000000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word64.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000010)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_right 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_right 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_right 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x0000000000000010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s13))
+[GOOD] (assert (= (table0 #x0000000000000002) s21))
+[GOOD] (assert (= (table0 #x0000000000000003) s22))
+[GOOD] (assert (= (table0 #x0000000000000004) s23))
+[GOOD] (assert (= (table0 #x0000000000000005) s24))
+[GOOD] (assert (= (table0 #x0000000000000006) s25))
+[GOOD] (assert (= (table0 #x0000000000000007) s26))
+[GOOD] (assert (= (table0 #x0000000000000008) s27))
+[GOOD] (assert (= (table0 #x0000000000000009) s28))
+[GOOD] (assert (= (table0 #x000000000000000a) s29))
+[GOOD] (assert (= (table0 #x000000000000000b) s30))
+[GOOD] (assert (= (table0 #x000000000000000c) s31))
+[GOOD] (assert (= (table0 #x000000000000000d) s32))
+[GOOD] (assert (= (table0 #x000000000000000e) s33))
+[GOOD] (assert (= (table0 #x000000000000000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int16_Word8.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_right 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_right 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_right 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x10 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s13))
+[GOOD] (assert (= (table0 #x02) s21))
+[GOOD] (assert (= (table0 #x03) s22))
+[GOOD] (assert (= (table0 #x04) s23))
+[GOOD] (assert (= (table0 #x05) s24))
+[GOOD] (assert (= (table0 #x06) s25))
+[GOOD] (assert (= (table0 #x07) s26))
+[GOOD] (assert (= (table0 #x08) s27))
+[GOOD] (assert (= (table0 #x09) s28))
+[GOOD] (assert (= (table0 #x0a) s29))
+[GOOD] (assert (= (table0 #x0b) s30))
+[GOOD] (assert (= (table0 #x0c) s31))
+[GOOD] (assert (= (table0 #x0d) s32))
+[GOOD] (assert (= (table0 #x0e) s33))
+[GOOD] (assert (= (table0 #x0f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word16.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_right 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_right 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_right 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_right 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x0020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s15))
+[GOOD] (assert (= (table0 #x0002) s25))
+[GOOD] (assert (= (table0 #x0003) s26))
+[GOOD] (assert (= (table0 #x0004) s27))
+[GOOD] (assert (= (table0 #x0005) s28))
+[GOOD] (assert (= (table0 #x0006) s29))
+[GOOD] (assert (= (table0 #x0007) s30))
+[GOOD] (assert (= (table0 #x0008) s31))
+[GOOD] (assert (= (table0 #x0009) s32))
+[GOOD] (assert (= (table0 #x000a) s33))
+[GOOD] (assert (= (table0 #x000b) s34))
+[GOOD] (assert (= (table0 #x000c) s35))
+[GOOD] (assert (= (table0 #x000d) s36))
+[GOOD] (assert (= (table0 #x000e) s37))
+[GOOD] (assert (= (table0 #x000f) s38))
+[GOOD] (assert (= (table0 #x0010) s39))
+[GOOD] (assert (= (table0 #x0011) s40))
+[GOOD] (assert (= (table0 #x0012) s41))
+[GOOD] (assert (= (table0 #x0013) s42))
+[GOOD] (assert (= (table0 #x0014) s43))
+[GOOD] (assert (= (table0 #x0015) s44))
+[GOOD] (assert (= (table0 #x0016) s45))
+[GOOD] (assert (= (table0 #x0017) s46))
+[GOOD] (assert (= (table0 #x0018) s47))
+[GOOD] (assert (= (table0 #x0019) s48))
+[GOOD] (assert (= (table0 #x001a) s49))
+[GOOD] (assert (= (table0 #x001b) s50))
+[GOOD] (assert (= (table0 #x001c) s51))
+[GOOD] (assert (= (table0 #x001d) s52))
+[GOOD] (assert (= (table0 #x001e) s53))
+[GOOD] (assert (= (table0 #x001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word32.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_right 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_right 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_right 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_right 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x00000020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s15))
+[GOOD] (assert (= (table0 #x00000002) s25))
+[GOOD] (assert (= (table0 #x00000003) s26))
+[GOOD] (assert (= (table0 #x00000004) s27))
+[GOOD] (assert (= (table0 #x00000005) s28))
+[GOOD] (assert (= (table0 #x00000006) s29))
+[GOOD] (assert (= (table0 #x00000007) s30))
+[GOOD] (assert (= (table0 #x00000008) s31))
+[GOOD] (assert (= (table0 #x00000009) s32))
+[GOOD] (assert (= (table0 #x0000000a) s33))
+[GOOD] (assert (= (table0 #x0000000b) s34))
+[GOOD] (assert (= (table0 #x0000000c) s35))
+[GOOD] (assert (= (table0 #x0000000d) s36))
+[GOOD] (assert (= (table0 #x0000000e) s37))
+[GOOD] (assert (= (table0 #x0000000f) s38))
+[GOOD] (assert (= (table0 #x00000010) s39))
+[GOOD] (assert (= (table0 #x00000011) s40))
+[GOOD] (assert (= (table0 #x00000012) s41))
+[GOOD] (assert (= (table0 #x00000013) s42))
+[GOOD] (assert (= (table0 #x00000014) s43))
+[GOOD] (assert (= (table0 #x00000015) s44))
+[GOOD] (assert (= (table0 #x00000016) s45))
+[GOOD] (assert (= (table0 #x00000017) s46))
+[GOOD] (assert (= (table0 #x00000018) s47))
+[GOOD] (assert (= (table0 #x00000019) s48))
+[GOOD] (assert (= (table0 #x0000001a) s49))
+[GOOD] (assert (= (table0 #x0000001b) s50))
+[GOOD] (assert (= (table0 #x0000001c) s51))
+[GOOD] (assert (= (table0 #x0000001d) s52))
+[GOOD] (assert (= (table0 #x0000001e) s53))
+[GOOD] (assert (= (table0 #x0000001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word64.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_right 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_right 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_right 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_right 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x0000000000000020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s15))
+[GOOD] (assert (= (table0 #x0000000000000002) s25))
+[GOOD] (assert (= (table0 #x0000000000000003) s26))
+[GOOD] (assert (= (table0 #x0000000000000004) s27))
+[GOOD] (assert (= (table0 #x0000000000000005) s28))
+[GOOD] (assert (= (table0 #x0000000000000006) s29))
+[GOOD] (assert (= (table0 #x0000000000000007) s30))
+[GOOD] (assert (= (table0 #x0000000000000008) s31))
+[GOOD] (assert (= (table0 #x0000000000000009) s32))
+[GOOD] (assert (= (table0 #x000000000000000a) s33))
+[GOOD] (assert (= (table0 #x000000000000000b) s34))
+[GOOD] (assert (= (table0 #x000000000000000c) s35))
+[GOOD] (assert (= (table0 #x000000000000000d) s36))
+[GOOD] (assert (= (table0 #x000000000000000e) s37))
+[GOOD] (assert (= (table0 #x000000000000000f) s38))
+[GOOD] (assert (= (table0 #x0000000000000010) s39))
+[GOOD] (assert (= (table0 #x0000000000000011) s40))
+[GOOD] (assert (= (table0 #x0000000000000012) s41))
+[GOOD] (assert (= (table0 #x0000000000000013) s42))
+[GOOD] (assert (= (table0 #x0000000000000014) s43))
+[GOOD] (assert (= (table0 #x0000000000000015) s44))
+[GOOD] (assert (= (table0 #x0000000000000016) s45))
+[GOOD] (assert (= (table0 #x0000000000000017) s46))
+[GOOD] (assert (= (table0 #x0000000000000018) s47))
+[GOOD] (assert (= (table0 #x0000000000000019) s48))
+[GOOD] (assert (= (table0 #x000000000000001a) s49))
+[GOOD] (assert (= (table0 #x000000000000001b) s50))
+[GOOD] (assert (= (table0 #x000000000000001c) s51))
+[GOOD] (assert (= (table0 #x000000000000001d) s52))
+[GOOD] (assert (= (table0 #x000000000000001e) s53))
+[GOOD] (assert (= (table0 #x000000000000001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int32_Word8.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_right 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_right 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_right 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_right 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x20 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s15))
+[GOOD] (assert (= (table0 #x02) s25))
+[GOOD] (assert (= (table0 #x03) s26))
+[GOOD] (assert (= (table0 #x04) s27))
+[GOOD] (assert (= (table0 #x05) s28))
+[GOOD] (assert (= (table0 #x06) s29))
+[GOOD] (assert (= (table0 #x07) s30))
+[GOOD] (assert (= (table0 #x08) s31))
+[GOOD] (assert (= (table0 #x09) s32))
+[GOOD] (assert (= (table0 #x0a) s33))
+[GOOD] (assert (= (table0 #x0b) s34))
+[GOOD] (assert (= (table0 #x0c) s35))
+[GOOD] (assert (= (table0 #x0d) s36))
+[GOOD] (assert (= (table0 #x0e) s37))
+[GOOD] (assert (= (table0 #x0f) s38))
+[GOOD] (assert (= (table0 #x10) s39))
+[GOOD] (assert (= (table0 #x11) s40))
+[GOOD] (assert (= (table0 #x12) s41))
+[GOOD] (assert (= (table0 #x13) s42))
+[GOOD] (assert (= (table0 #x14) s43))
+[GOOD] (assert (= (table0 #x15) s44))
+[GOOD] (assert (= (table0 #x16) s45))
+[GOOD] (assert (= (table0 #x17) s46))
+[GOOD] (assert (= (table0 #x18) s47))
+[GOOD] (assert (= (table0 #x19) s48))
+[GOOD] (assert (= (table0 #x1a) s49))
+[GOOD] (assert (= (table0 #x1b) s50))
+[GOOD] (assert (= (table0 #x1c) s51))
+[GOOD] (assert (= (table0 #x1d) s52))
+[GOOD] (assert (= (table0 #x1e) s53))
+[GOOD] (assert (= (table0 #x1f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word16.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_right 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_right 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_right 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_right 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_right 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_right 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_right 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_right 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_right 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_right 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_right 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_right 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_right 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_right 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_right 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_right 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_right 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_right 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_right 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_right 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_right 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_right 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_right 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_right 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_right 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_right 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_right 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_right 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_right 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_right 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_right 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_right 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_right 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_right 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_right 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_right 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_right 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x0040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s17))
+[GOOD] (assert (= (table0 #x0002) s29))
+[GOOD] (assert (= (table0 #x0003) s30))
+[GOOD] (assert (= (table0 #x0004) s31))
+[GOOD] (assert (= (table0 #x0005) s32))
+[GOOD] (assert (= (table0 #x0006) s33))
+[GOOD] (assert (= (table0 #x0007) s34))
+[GOOD] (assert (= (table0 #x0008) s35))
+[GOOD] (assert (= (table0 #x0009) s36))
+[GOOD] (assert (= (table0 #x000a) s37))
+[GOOD] (assert (= (table0 #x000b) s38))
+[GOOD] (assert (= (table0 #x000c) s39))
+[GOOD] (assert (= (table0 #x000d) s40))
+[GOOD] (assert (= (table0 #x000e) s41))
+[GOOD] (assert (= (table0 #x000f) s42))
+[GOOD] (assert (= (table0 #x0010) s43))
+[GOOD] (assert (= (table0 #x0011) s44))
+[GOOD] (assert (= (table0 #x0012) s45))
+[GOOD] (assert (= (table0 #x0013) s46))
+[GOOD] (assert (= (table0 #x0014) s47))
+[GOOD] (assert (= (table0 #x0015) s48))
+[GOOD] (assert (= (table0 #x0016) s49))
+[GOOD] (assert (= (table0 #x0017) s50))
+[GOOD] (assert (= (table0 #x0018) s51))
+[GOOD] (assert (= (table0 #x0019) s52))
+[GOOD] (assert (= (table0 #x001a) s53))
+[GOOD] (assert (= (table0 #x001b) s54))
+[GOOD] (assert (= (table0 #x001c) s55))
+[GOOD] (assert (= (table0 #x001d) s56))
+[GOOD] (assert (= (table0 #x001e) s57))
+[GOOD] (assert (= (table0 #x001f) s58))
+[GOOD] (assert (= (table0 #x0020) s59))
+[GOOD] (assert (= (table0 #x0021) s60))
+[GOOD] (assert (= (table0 #x0022) s61))
+[GOOD] (assert (= (table0 #x0023) s62))
+[GOOD] (assert (= (table0 #x0024) s63))
+[GOOD] (assert (= (table0 #x0025) s64))
+[GOOD] (assert (= (table0 #x0026) s65))
+[GOOD] (assert (= (table0 #x0027) s66))
+[GOOD] (assert (= (table0 #x0028) s67))
+[GOOD] (assert (= (table0 #x0029) s68))
+[GOOD] (assert (= (table0 #x002a) s69))
+[GOOD] (assert (= (table0 #x002b) s70))
+[GOOD] (assert (= (table0 #x002c) s71))
+[GOOD] (assert (= (table0 #x002d) s72))
+[GOOD] (assert (= (table0 #x002e) s73))
+[GOOD] (assert (= (table0 #x002f) s74))
+[GOOD] (assert (= (table0 #x0030) s75))
+[GOOD] (assert (= (table0 #x0031) s76))
+[GOOD] (assert (= (table0 #x0032) s77))
+[GOOD] (assert (= (table0 #x0033) s78))
+[GOOD] (assert (= (table0 #x0034) s79))
+[GOOD] (assert (= (table0 #x0035) s80))
+[GOOD] (assert (= (table0 #x0036) s81))
+[GOOD] (assert (= (table0 #x0037) s82))
+[GOOD] (assert (= (table0 #x0038) s83))
+[GOOD] (assert (= (table0 #x0039) s84))
+[GOOD] (assert (= (table0 #x003a) s85))
+[GOOD] (assert (= (table0 #x003b) s86))
+[GOOD] (assert (= (table0 #x003c) s87))
+[GOOD] (assert (= (table0 #x003d) s88))
+[GOOD] (assert (= (table0 #x003e) s89))
+[GOOD] (assert (= (table0 #x003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word32.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_right 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_right 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_right 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_right 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_right 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_right 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_right 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_right 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_right 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_right 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_right 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_right 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_right 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_right 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_right 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_right 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_right 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_right 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_right 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_right 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_right 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_right 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_right 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_right 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_right 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_right 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_right 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_right 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_right 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_right 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_right 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_right 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_right 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_right 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_right 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_right 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_right 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x00000040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s17))
+[GOOD] (assert (= (table0 #x00000002) s29))
+[GOOD] (assert (= (table0 #x00000003) s30))
+[GOOD] (assert (= (table0 #x00000004) s31))
+[GOOD] (assert (= (table0 #x00000005) s32))
+[GOOD] (assert (= (table0 #x00000006) s33))
+[GOOD] (assert (= (table0 #x00000007) s34))
+[GOOD] (assert (= (table0 #x00000008) s35))
+[GOOD] (assert (= (table0 #x00000009) s36))
+[GOOD] (assert (= (table0 #x0000000a) s37))
+[GOOD] (assert (= (table0 #x0000000b) s38))
+[GOOD] (assert (= (table0 #x0000000c) s39))
+[GOOD] (assert (= (table0 #x0000000d) s40))
+[GOOD] (assert (= (table0 #x0000000e) s41))
+[GOOD] (assert (= (table0 #x0000000f) s42))
+[GOOD] (assert (= (table0 #x00000010) s43))
+[GOOD] (assert (= (table0 #x00000011) s44))
+[GOOD] (assert (= (table0 #x00000012) s45))
+[GOOD] (assert (= (table0 #x00000013) s46))
+[GOOD] (assert (= (table0 #x00000014) s47))
+[GOOD] (assert (= (table0 #x00000015) s48))
+[GOOD] (assert (= (table0 #x00000016) s49))
+[GOOD] (assert (= (table0 #x00000017) s50))
+[GOOD] (assert (= (table0 #x00000018) s51))
+[GOOD] (assert (= (table0 #x00000019) s52))
+[GOOD] (assert (= (table0 #x0000001a) s53))
+[GOOD] (assert (= (table0 #x0000001b) s54))
+[GOOD] (assert (= (table0 #x0000001c) s55))
+[GOOD] (assert (= (table0 #x0000001d) s56))
+[GOOD] (assert (= (table0 #x0000001e) s57))
+[GOOD] (assert (= (table0 #x0000001f) s58))
+[GOOD] (assert (= (table0 #x00000020) s59))
+[GOOD] (assert (= (table0 #x00000021) s60))
+[GOOD] (assert (= (table0 #x00000022) s61))
+[GOOD] (assert (= (table0 #x00000023) s62))
+[GOOD] (assert (= (table0 #x00000024) s63))
+[GOOD] (assert (= (table0 #x00000025) s64))
+[GOOD] (assert (= (table0 #x00000026) s65))
+[GOOD] (assert (= (table0 #x00000027) s66))
+[GOOD] (assert (= (table0 #x00000028) s67))
+[GOOD] (assert (= (table0 #x00000029) s68))
+[GOOD] (assert (= (table0 #x0000002a) s69))
+[GOOD] (assert (= (table0 #x0000002b) s70))
+[GOOD] (assert (= (table0 #x0000002c) s71))
+[GOOD] (assert (= (table0 #x0000002d) s72))
+[GOOD] (assert (= (table0 #x0000002e) s73))
+[GOOD] (assert (= (table0 #x0000002f) s74))
+[GOOD] (assert (= (table0 #x00000030) s75))
+[GOOD] (assert (= (table0 #x00000031) s76))
+[GOOD] (assert (= (table0 #x00000032) s77))
+[GOOD] (assert (= (table0 #x00000033) s78))
+[GOOD] (assert (= (table0 #x00000034) s79))
+[GOOD] (assert (= (table0 #x00000035) s80))
+[GOOD] (assert (= (table0 #x00000036) s81))
+[GOOD] (assert (= (table0 #x00000037) s82))
+[GOOD] (assert (= (table0 #x00000038) s83))
+[GOOD] (assert (= (table0 #x00000039) s84))
+[GOOD] (assert (= (table0 #x0000003a) s85))
+[GOOD] (assert (= (table0 #x0000003b) s86))
+[GOOD] (assert (= (table0 #x0000003c) s87))
+[GOOD] (assert (= (table0 #x0000003d) s88))
+[GOOD] (assert (= (table0 #x0000003e) s89))
+[GOOD] (assert (= (table0 #x0000003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word64.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_right 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_right 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_right 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_right 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_right 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_right 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_right 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_right 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_right 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_right 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_right 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_right 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_right 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_right 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_right 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_right 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_right 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_right 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_right 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_right 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_right 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_right 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_right 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_right 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_right 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_right 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_right 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_right 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_right 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_right 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_right 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_right 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_right 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_right 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_right 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_right 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_right 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x0000000000000040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s17))
+[GOOD] (assert (= (table0 #x0000000000000002) s29))
+[GOOD] (assert (= (table0 #x0000000000000003) s30))
+[GOOD] (assert (= (table0 #x0000000000000004) s31))
+[GOOD] (assert (= (table0 #x0000000000000005) s32))
+[GOOD] (assert (= (table0 #x0000000000000006) s33))
+[GOOD] (assert (= (table0 #x0000000000000007) s34))
+[GOOD] (assert (= (table0 #x0000000000000008) s35))
+[GOOD] (assert (= (table0 #x0000000000000009) s36))
+[GOOD] (assert (= (table0 #x000000000000000a) s37))
+[GOOD] (assert (= (table0 #x000000000000000b) s38))
+[GOOD] (assert (= (table0 #x000000000000000c) s39))
+[GOOD] (assert (= (table0 #x000000000000000d) s40))
+[GOOD] (assert (= (table0 #x000000000000000e) s41))
+[GOOD] (assert (= (table0 #x000000000000000f) s42))
+[GOOD] (assert (= (table0 #x0000000000000010) s43))
+[GOOD] (assert (= (table0 #x0000000000000011) s44))
+[GOOD] (assert (= (table0 #x0000000000000012) s45))
+[GOOD] (assert (= (table0 #x0000000000000013) s46))
+[GOOD] (assert (= (table0 #x0000000000000014) s47))
+[GOOD] (assert (= (table0 #x0000000000000015) s48))
+[GOOD] (assert (= (table0 #x0000000000000016) s49))
+[GOOD] (assert (= (table0 #x0000000000000017) s50))
+[GOOD] (assert (= (table0 #x0000000000000018) s51))
+[GOOD] (assert (= (table0 #x0000000000000019) s52))
+[GOOD] (assert (= (table0 #x000000000000001a) s53))
+[GOOD] (assert (= (table0 #x000000000000001b) s54))
+[GOOD] (assert (= (table0 #x000000000000001c) s55))
+[GOOD] (assert (= (table0 #x000000000000001d) s56))
+[GOOD] (assert (= (table0 #x000000000000001e) s57))
+[GOOD] (assert (= (table0 #x000000000000001f) s58))
+[GOOD] (assert (= (table0 #x0000000000000020) s59))
+[GOOD] (assert (= (table0 #x0000000000000021) s60))
+[GOOD] (assert (= (table0 #x0000000000000022) s61))
+[GOOD] (assert (= (table0 #x0000000000000023) s62))
+[GOOD] (assert (= (table0 #x0000000000000024) s63))
+[GOOD] (assert (= (table0 #x0000000000000025) s64))
+[GOOD] (assert (= (table0 #x0000000000000026) s65))
+[GOOD] (assert (= (table0 #x0000000000000027) s66))
+[GOOD] (assert (= (table0 #x0000000000000028) s67))
+[GOOD] (assert (= (table0 #x0000000000000029) s68))
+[GOOD] (assert (= (table0 #x000000000000002a) s69))
+[GOOD] (assert (= (table0 #x000000000000002b) s70))
+[GOOD] (assert (= (table0 #x000000000000002c) s71))
+[GOOD] (assert (= (table0 #x000000000000002d) s72))
+[GOOD] (assert (= (table0 #x000000000000002e) s73))
+[GOOD] (assert (= (table0 #x000000000000002f) s74))
+[GOOD] (assert (= (table0 #x0000000000000030) s75))
+[GOOD] (assert (= (table0 #x0000000000000031) s76))
+[GOOD] (assert (= (table0 #x0000000000000032) s77))
+[GOOD] (assert (= (table0 #x0000000000000033) s78))
+[GOOD] (assert (= (table0 #x0000000000000034) s79))
+[GOOD] (assert (= (table0 #x0000000000000035) s80))
+[GOOD] (assert (= (table0 #x0000000000000036) s81))
+[GOOD] (assert (= (table0 #x0000000000000037) s82))
+[GOOD] (assert (= (table0 #x0000000000000038) s83))
+[GOOD] (assert (= (table0 #x0000000000000039) s84))
+[GOOD] (assert (= (table0 #x000000000000003a) s85))
+[GOOD] (assert (= (table0 #x000000000000003b) s86))
+[GOOD] (assert (= (table0 #x000000000000003c) s87))
+[GOOD] (assert (= (table0 #x000000000000003d) s88))
+[GOOD] (assert (= (table0 #x000000000000003e) s89))
+[GOOD] (assert (= (table0 #x000000000000003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int64_Word8.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_right 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_right 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_right 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_right 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_right 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_right 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_right 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_right 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_right 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_right 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_right 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_right 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_right 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_right 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_right 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_right 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_right 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_right 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_right 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_right 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_right 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_right 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_right 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_right 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_right 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_right 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_right 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_right 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_right 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_right 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_right 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_right 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_right 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_right 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_right 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_right 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_right 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x40 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s17))
+[GOOD] (assert (= (table0 #x02) s29))
+[GOOD] (assert (= (table0 #x03) s30))
+[GOOD] (assert (= (table0 #x04) s31))
+[GOOD] (assert (= (table0 #x05) s32))
+[GOOD] (assert (= (table0 #x06) s33))
+[GOOD] (assert (= (table0 #x07) s34))
+[GOOD] (assert (= (table0 #x08) s35))
+[GOOD] (assert (= (table0 #x09) s36))
+[GOOD] (assert (= (table0 #x0a) s37))
+[GOOD] (assert (= (table0 #x0b) s38))
+[GOOD] (assert (= (table0 #x0c) s39))
+[GOOD] (assert (= (table0 #x0d) s40))
+[GOOD] (assert (= (table0 #x0e) s41))
+[GOOD] (assert (= (table0 #x0f) s42))
+[GOOD] (assert (= (table0 #x10) s43))
+[GOOD] (assert (= (table0 #x11) s44))
+[GOOD] (assert (= (table0 #x12) s45))
+[GOOD] (assert (= (table0 #x13) s46))
+[GOOD] (assert (= (table0 #x14) s47))
+[GOOD] (assert (= (table0 #x15) s48))
+[GOOD] (assert (= (table0 #x16) s49))
+[GOOD] (assert (= (table0 #x17) s50))
+[GOOD] (assert (= (table0 #x18) s51))
+[GOOD] (assert (= (table0 #x19) s52))
+[GOOD] (assert (= (table0 #x1a) s53))
+[GOOD] (assert (= (table0 #x1b) s54))
+[GOOD] (assert (= (table0 #x1c) s55))
+[GOOD] (assert (= (table0 #x1d) s56))
+[GOOD] (assert (= (table0 #x1e) s57))
+[GOOD] (assert (= (table0 #x1f) s58))
+[GOOD] (assert (= (table0 #x20) s59))
+[GOOD] (assert (= (table0 #x21) s60))
+[GOOD] (assert (= (table0 #x22) s61))
+[GOOD] (assert (= (table0 #x23) s62))
+[GOOD] (assert (= (table0 #x24) s63))
+[GOOD] (assert (= (table0 #x25) s64))
+[GOOD] (assert (= (table0 #x26) s65))
+[GOOD] (assert (= (table0 #x27) s66))
+[GOOD] (assert (= (table0 #x28) s67))
+[GOOD] (assert (= (table0 #x29) s68))
+[GOOD] (assert (= (table0 #x2a) s69))
+[GOOD] (assert (= (table0 #x2b) s70))
+[GOOD] (assert (= (table0 #x2c) s71))
+[GOOD] (assert (= (table0 #x2d) s72))
+[GOOD] (assert (= (table0 #x2e) s73))
+[GOOD] (assert (= (table0 #x2f) s74))
+[GOOD] (assert (= (table0 #x30) s75))
+[GOOD] (assert (= (table0 #x31) s76))
+[GOOD] (assert (= (table0 #x32) s77))
+[GOOD] (assert (= (table0 #x33) s78))
+[GOOD] (assert (= (table0 #x34) s79))
+[GOOD] (assert (= (table0 #x35) s80))
+[GOOD] (assert (= (table0 #x36) s81))
+[GOOD] (assert (= (table0 #x37) s82))
+[GOOD] (assert (= (table0 #x38) s83))
+[GOOD] (assert (= (table0 #x39) s84))
+[GOOD] (assert (= (table0 #x3a) s85))
+[GOOD] (assert (= (table0 #x3b) s86))
+[GOOD] (assert (= (table0 #x3c) s87))
+[GOOD] (assert (= (table0 #x3d) s88))
+[GOOD] (assert (= (table0 #x3e) s89))
+[GOOD] (assert (= (table0 #x3f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word16.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0008)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_right 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_right 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x0008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s11))
+[GOOD] (assert (= (table0 #x0002) s17))
+[GOOD] (assert (= (table0 #x0003) s18))
+[GOOD] (assert (= (table0 #x0004) s19))
+[GOOD] (assert (= (table0 #x0005) s20))
+[GOOD] (assert (= (table0 #x0006) s21))
+[GOOD] (assert (= (table0 #x0007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word32.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000008)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_right 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_right 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x00000008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s11))
+[GOOD] (assert (= (table0 #x00000002) s17))
+[GOOD] (assert (= (table0 #x00000003) s18))
+[GOOD] (assert (= (table0 #x00000004) s19))
+[GOOD] (assert (= (table0 #x00000005) s20))
+[GOOD] (assert (= (table0 #x00000006) s21))
+[GOOD] (assert (= (table0 #x00000007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word64.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000008)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_right 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_right 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x0000000000000008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s11))
+[GOOD] (assert (= (table0 #x0000000000000002) s17))
+[GOOD] (assert (= (table0 #x0000000000000003) s18))
+[GOOD] (assert (= (table0 #x0000000000000004) s19))
+[GOOD] (assert (= (table0 #x0000000000000005) s20))
+[GOOD] (assert (= (table0 #x0000000000000006) s21))
+[GOOD] (assert (= (table0 #x0000000000000007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Int8_Word8.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_right 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_right 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x08 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s11))
+[GOOD] (assert (= (table0 #x02) s17))
+[GOOD] (assert (= (table0 #x03) s18))
+[GOOD] (assert (= (table0 #x04) s19))
+[GOOD] (assert (= (table0 #x05) s20))
+[GOOD] (assert (= (table0 #x06) s21))
+[GOOD] (assert (= (table0 #x07) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word16.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0010)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_right 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_right 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_right 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x0010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s13))
+[GOOD] (assert (= (table0 #x0002) s21))
+[GOOD] (assert (= (table0 #x0003) s22))
+[GOOD] (assert (= (table0 #x0004) s23))
+[GOOD] (assert (= (table0 #x0005) s24))
+[GOOD] (assert (= (table0 #x0006) s25))
+[GOOD] (assert (= (table0 #x0007) s26))
+[GOOD] (assert (= (table0 #x0008) s27))
+[GOOD] (assert (= (table0 #x0009) s28))
+[GOOD] (assert (= (table0 #x000a) s29))
+[GOOD] (assert (= (table0 #x000b) s30))
+[GOOD] (assert (= (table0 #x000c) s31))
+[GOOD] (assert (= (table0 #x000d) s32))
+[GOOD] (assert (= (table0 #x000e) s33))
+[GOOD] (assert (= (table0 #x000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word32.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000010)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_right 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_right 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_right 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x00000010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s13))
+[GOOD] (assert (= (table0 #x00000002) s21))
+[GOOD] (assert (= (table0 #x00000003) s22))
+[GOOD] (assert (= (table0 #x00000004) s23))
+[GOOD] (assert (= (table0 #x00000005) s24))
+[GOOD] (assert (= (table0 #x00000006) s25))
+[GOOD] (assert (= (table0 #x00000007) s26))
+[GOOD] (assert (= (table0 #x00000008) s27))
+[GOOD] (assert (= (table0 #x00000009) s28))
+[GOOD] (assert (= (table0 #x0000000a) s29))
+[GOOD] (assert (= (table0 #x0000000b) s30))
+[GOOD] (assert (= (table0 #x0000000c) s31))
+[GOOD] (assert (= (table0 #x0000000d) s32))
+[GOOD] (assert (= (table0 #x0000000e) s33))
+[GOOD] (assert (= (table0 #x0000000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word64.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000010)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_right 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_right 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_right 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x0000000000000010 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s13))
+[GOOD] (assert (= (table0 #x0000000000000002) s21))
+[GOOD] (assert (= (table0 #x0000000000000003) s22))
+[GOOD] (assert (= (table0 #x0000000000000004) s23))
+[GOOD] (assert (= (table0 #x0000000000000005) s24))
+[GOOD] (assert (= (table0 #x0000000000000006) s25))
+[GOOD] (assert (= (table0 #x0000000000000007) s26))
+[GOOD] (assert (= (table0 #x0000000000000008) s27))
+[GOOD] (assert (= (table0 #x0000000000000009) s28))
+[GOOD] (assert (= (table0 #x000000000000000a) s29))
+[GOOD] (assert (= (table0 #x000000000000000b) s30))
+[GOOD] (assert (= (table0 #x000000000000000c) s31))
+[GOOD] (assert (= (table0 #x000000000000000d) s32))
+[GOOD] (assert (= (table0 #x000000000000000e) s33))
+[GOOD] (assert (= (table0 #x000000000000000f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word16_Word8.gold
@@ -0,0 +1,83 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x10)
+[GOOD] (define-fun s35 () (_ BitVec 16) #x0000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 16))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 16))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 16) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s14 () (_ BitVec 16) (ite s12 s13 s0))
+[GOOD] (define-fun s15 () (_ BitVec 16) ((_ rotate_right 2) s14))
+[GOOD] (define-fun s16 () (_ BitVec 16) (ite s10 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 16) ((_ rotate_right 4) s16))
+[GOOD] (define-fun s18 () (_ BitVec 16) (ite s8 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 16) ((_ rotate_right 8) s18))
+[GOOD] (define-fun s20 () (_ BitVec 16) (ite s6 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 16) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s22 () (_ BitVec 16) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s23 () (_ BitVec 16) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s24 () (_ BitVec 16) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s25 () (_ BitVec 16) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s26 () (_ BitVec 16) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s27 () (_ BitVec 16) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s28 () (_ BitVec 16) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s29 () (_ BitVec 16) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s30 () (_ BitVec 16) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s31 () (_ BitVec 16) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s32 () (_ BitVec 16) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s33 () (_ BitVec 16) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s34 () (_ BitVec 16) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s36 () (_ BitVec 16) (ite (bvule #x10 s3) s35 (table0 s3)))
+[GOOD] (define-fun s37 () Bool (= s20 s36))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s13))
+[GOOD] (assert (= (table0 #x02) s21))
+[GOOD] (assert (= (table0 #x03) s22))
+[GOOD] (assert (= (table0 #x04) s23))
+[GOOD] (assert (= (table0 #x05) s24))
+[GOOD] (assert (= (table0 #x06) s25))
+[GOOD] (assert (= (table0 #x07) s26))
+[GOOD] (assert (= (table0 #x08) s27))
+[GOOD] (assert (= (table0 #x09) s28))
+[GOOD] (assert (= (table0 #x0a) s29))
+[GOOD] (assert (= (table0 #x0b) s30))
+[GOOD] (assert (= (table0 #x0c) s31))
+[GOOD] (assert (= (table0 #x0d) s32))
+[GOOD] (assert (= (table0 #x0e) s33))
+[GOOD] (assert (= (table0 #x0f) s34))
+[GOOD] (assert (not s37))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word16.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_right 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_right 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_right 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_right 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x0020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s15))
+[GOOD] (assert (= (table0 #x0002) s25))
+[GOOD] (assert (= (table0 #x0003) s26))
+[GOOD] (assert (= (table0 #x0004) s27))
+[GOOD] (assert (= (table0 #x0005) s28))
+[GOOD] (assert (= (table0 #x0006) s29))
+[GOOD] (assert (= (table0 #x0007) s30))
+[GOOD] (assert (= (table0 #x0008) s31))
+[GOOD] (assert (= (table0 #x0009) s32))
+[GOOD] (assert (= (table0 #x000a) s33))
+[GOOD] (assert (= (table0 #x000b) s34))
+[GOOD] (assert (= (table0 #x000c) s35))
+[GOOD] (assert (= (table0 #x000d) s36))
+[GOOD] (assert (= (table0 #x000e) s37))
+[GOOD] (assert (= (table0 #x000f) s38))
+[GOOD] (assert (= (table0 #x0010) s39))
+[GOOD] (assert (= (table0 #x0011) s40))
+[GOOD] (assert (= (table0 #x0012) s41))
+[GOOD] (assert (= (table0 #x0013) s42))
+[GOOD] (assert (= (table0 #x0014) s43))
+[GOOD] (assert (= (table0 #x0015) s44))
+[GOOD] (assert (= (table0 #x0016) s45))
+[GOOD] (assert (= (table0 #x0017) s46))
+[GOOD] (assert (= (table0 #x0018) s47))
+[GOOD] (assert (= (table0 #x0019) s48))
+[GOOD] (assert (= (table0 #x001a) s49))
+[GOOD] (assert (= (table0 #x001b) s50))
+[GOOD] (assert (= (table0 #x001c) s51))
+[GOOD] (assert (= (table0 #x001d) s52))
+[GOOD] (assert (= (table0 #x001e) s53))
+[GOOD] (assert (= (table0 #x001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word32.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000020)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_right 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_right 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_right 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_right 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x00000020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s15))
+[GOOD] (assert (= (table0 #x00000002) s25))
+[GOOD] (assert (= (table0 #x00000003) s26))
+[GOOD] (assert (= (table0 #x00000004) s27))
+[GOOD] (assert (= (table0 #x00000005) s28))
+[GOOD] (assert (= (table0 #x00000006) s29))
+[GOOD] (assert (= (table0 #x00000007) s30))
+[GOOD] (assert (= (table0 #x00000008) s31))
+[GOOD] (assert (= (table0 #x00000009) s32))
+[GOOD] (assert (= (table0 #x0000000a) s33))
+[GOOD] (assert (= (table0 #x0000000b) s34))
+[GOOD] (assert (= (table0 #x0000000c) s35))
+[GOOD] (assert (= (table0 #x0000000d) s36))
+[GOOD] (assert (= (table0 #x0000000e) s37))
+[GOOD] (assert (= (table0 #x0000000f) s38))
+[GOOD] (assert (= (table0 #x00000010) s39))
+[GOOD] (assert (= (table0 #x00000011) s40))
+[GOOD] (assert (= (table0 #x00000012) s41))
+[GOOD] (assert (= (table0 #x00000013) s42))
+[GOOD] (assert (= (table0 #x00000014) s43))
+[GOOD] (assert (= (table0 #x00000015) s44))
+[GOOD] (assert (= (table0 #x00000016) s45))
+[GOOD] (assert (= (table0 #x00000017) s46))
+[GOOD] (assert (= (table0 #x00000018) s47))
+[GOOD] (assert (= (table0 #x00000019) s48))
+[GOOD] (assert (= (table0 #x0000001a) s49))
+[GOOD] (assert (= (table0 #x0000001b) s50))
+[GOOD] (assert (= (table0 #x0000001c) s51))
+[GOOD] (assert (= (table0 #x0000001d) s52))
+[GOOD] (assert (= (table0 #x0000001e) s53))
+[GOOD] (assert (= (table0 #x0000001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word64.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000020)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_right 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_right 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_right 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_right 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x0000000000000020 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s15))
+[GOOD] (assert (= (table0 #x0000000000000002) s25))
+[GOOD] (assert (= (table0 #x0000000000000003) s26))
+[GOOD] (assert (= (table0 #x0000000000000004) s27))
+[GOOD] (assert (= (table0 #x0000000000000005) s28))
+[GOOD] (assert (= (table0 #x0000000000000006) s29))
+[GOOD] (assert (= (table0 #x0000000000000007) s30))
+[GOOD] (assert (= (table0 #x0000000000000008) s31))
+[GOOD] (assert (= (table0 #x0000000000000009) s32))
+[GOOD] (assert (= (table0 #x000000000000000a) s33))
+[GOOD] (assert (= (table0 #x000000000000000b) s34))
+[GOOD] (assert (= (table0 #x000000000000000c) s35))
+[GOOD] (assert (= (table0 #x000000000000000d) s36))
+[GOOD] (assert (= (table0 #x000000000000000e) s37))
+[GOOD] (assert (= (table0 #x000000000000000f) s38))
+[GOOD] (assert (= (table0 #x0000000000000010) s39))
+[GOOD] (assert (= (table0 #x0000000000000011) s40))
+[GOOD] (assert (= (table0 #x0000000000000012) s41))
+[GOOD] (assert (= (table0 #x0000000000000013) s42))
+[GOOD] (assert (= (table0 #x0000000000000014) s43))
+[GOOD] (assert (= (table0 #x0000000000000015) s44))
+[GOOD] (assert (= (table0 #x0000000000000016) s45))
+[GOOD] (assert (= (table0 #x0000000000000017) s46))
+[GOOD] (assert (= (table0 #x0000000000000018) s47))
+[GOOD] (assert (= (table0 #x0000000000000019) s48))
+[GOOD] (assert (= (table0 #x000000000000001a) s49))
+[GOOD] (assert (= (table0 #x000000000000001b) s50))
+[GOOD] (assert (= (table0 #x000000000000001c) s51))
+[GOOD] (assert (= (table0 #x000000000000001d) s52))
+[GOOD] (assert (= (table0 #x000000000000001e) s53))
+[GOOD] (assert (= (table0 #x000000000000001f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word32_Word8.gold
@@ -0,0 +1,119 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x20)
+[GOOD] (define-fun s55 () (_ BitVec 32) #x00000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 32))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 32))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 32) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s16 () (_ BitVec 32) (ite s14 s15 s0))
+[GOOD] (define-fun s17 () (_ BitVec 32) ((_ rotate_right 2) s16))
+[GOOD] (define-fun s18 () (_ BitVec 32) (ite s12 s17 s16))
+[GOOD] (define-fun s19 () (_ BitVec 32) ((_ rotate_right 4) s18))
+[GOOD] (define-fun s20 () (_ BitVec 32) (ite s10 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 32) ((_ rotate_right 8) s20))
+[GOOD] (define-fun s22 () (_ BitVec 32) (ite s8 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 32) ((_ rotate_right 16) s22))
+[GOOD] (define-fun s24 () (_ BitVec 32) (ite s6 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 32) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s26 () (_ BitVec 32) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s27 () (_ BitVec 32) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s28 () (_ BitVec 32) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s29 () (_ BitVec 32) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s30 () (_ BitVec 32) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s31 () (_ BitVec 32) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s32 () (_ BitVec 32) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s33 () (_ BitVec 32) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s34 () (_ BitVec 32) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s35 () (_ BitVec 32) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s36 () (_ BitVec 32) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s37 () (_ BitVec 32) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s38 () (_ BitVec 32) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s39 () (_ BitVec 32) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s40 () (_ BitVec 32) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s41 () (_ BitVec 32) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s42 () (_ BitVec 32) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s43 () (_ BitVec 32) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s44 () (_ BitVec 32) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s45 () (_ BitVec 32) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s46 () (_ BitVec 32) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s47 () (_ BitVec 32) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s48 () (_ BitVec 32) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s49 () (_ BitVec 32) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s50 () (_ BitVec 32) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s51 () (_ BitVec 32) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s52 () (_ BitVec 32) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s53 () (_ BitVec 32) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s54 () (_ BitVec 32) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s56 () (_ BitVec 32) (ite (bvule #x20 s3) s55 (table0 s3)))
+[GOOD] (define-fun s57 () Bool (= s24 s56))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s15))
+[GOOD] (assert (= (table0 #x02) s25))
+[GOOD] (assert (= (table0 #x03) s26))
+[GOOD] (assert (= (table0 #x04) s27))
+[GOOD] (assert (= (table0 #x05) s28))
+[GOOD] (assert (= (table0 #x06) s29))
+[GOOD] (assert (= (table0 #x07) s30))
+[GOOD] (assert (= (table0 #x08) s31))
+[GOOD] (assert (= (table0 #x09) s32))
+[GOOD] (assert (= (table0 #x0a) s33))
+[GOOD] (assert (= (table0 #x0b) s34))
+[GOOD] (assert (= (table0 #x0c) s35))
+[GOOD] (assert (= (table0 #x0d) s36))
+[GOOD] (assert (= (table0 #x0e) s37))
+[GOOD] (assert (= (table0 #x0f) s38))
+[GOOD] (assert (= (table0 #x10) s39))
+[GOOD] (assert (= (table0 #x11) s40))
+[GOOD] (assert (= (table0 #x12) s41))
+[GOOD] (assert (= (table0 #x13) s42))
+[GOOD] (assert (= (table0 #x14) s43))
+[GOOD] (assert (= (table0 #x15) s44))
+[GOOD] (assert (= (table0 #x16) s45))
+[GOOD] (assert (= (table0 #x17) s46))
+[GOOD] (assert (= (table0 #x18) s47))
+[GOOD] (assert (= (table0 #x19) s48))
+[GOOD] (assert (= (table0 #x1a) s49))
+[GOOD] (assert (= (table0 #x1b) s50))
+[GOOD] (assert (= (table0 #x1c) s51))
+[GOOD] (assert (= (table0 #x1d) s52))
+[GOOD] (assert (= (table0 #x1e) s53))
+[GOOD] (assert (= (table0 #x1f) s54))
+[GOOD] (assert (not s57))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word16.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_right 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_right 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_right 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_right 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_right 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_right 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_right 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_right 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_right 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_right 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_right 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_right 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_right 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_right 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_right 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_right 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_right 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_right 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_right 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_right 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_right 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_right 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_right 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_right 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_right 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_right 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_right 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_right 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_right 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_right 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_right 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_right 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_right 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_right 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_right 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_right 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_right 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x0040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s17))
+[GOOD] (assert (= (table0 #x0002) s29))
+[GOOD] (assert (= (table0 #x0003) s30))
+[GOOD] (assert (= (table0 #x0004) s31))
+[GOOD] (assert (= (table0 #x0005) s32))
+[GOOD] (assert (= (table0 #x0006) s33))
+[GOOD] (assert (= (table0 #x0007) s34))
+[GOOD] (assert (= (table0 #x0008) s35))
+[GOOD] (assert (= (table0 #x0009) s36))
+[GOOD] (assert (= (table0 #x000a) s37))
+[GOOD] (assert (= (table0 #x000b) s38))
+[GOOD] (assert (= (table0 #x000c) s39))
+[GOOD] (assert (= (table0 #x000d) s40))
+[GOOD] (assert (= (table0 #x000e) s41))
+[GOOD] (assert (= (table0 #x000f) s42))
+[GOOD] (assert (= (table0 #x0010) s43))
+[GOOD] (assert (= (table0 #x0011) s44))
+[GOOD] (assert (= (table0 #x0012) s45))
+[GOOD] (assert (= (table0 #x0013) s46))
+[GOOD] (assert (= (table0 #x0014) s47))
+[GOOD] (assert (= (table0 #x0015) s48))
+[GOOD] (assert (= (table0 #x0016) s49))
+[GOOD] (assert (= (table0 #x0017) s50))
+[GOOD] (assert (= (table0 #x0018) s51))
+[GOOD] (assert (= (table0 #x0019) s52))
+[GOOD] (assert (= (table0 #x001a) s53))
+[GOOD] (assert (= (table0 #x001b) s54))
+[GOOD] (assert (= (table0 #x001c) s55))
+[GOOD] (assert (= (table0 #x001d) s56))
+[GOOD] (assert (= (table0 #x001e) s57))
+[GOOD] (assert (= (table0 #x001f) s58))
+[GOOD] (assert (= (table0 #x0020) s59))
+[GOOD] (assert (= (table0 #x0021) s60))
+[GOOD] (assert (= (table0 #x0022) s61))
+[GOOD] (assert (= (table0 #x0023) s62))
+[GOOD] (assert (= (table0 #x0024) s63))
+[GOOD] (assert (= (table0 #x0025) s64))
+[GOOD] (assert (= (table0 #x0026) s65))
+[GOOD] (assert (= (table0 #x0027) s66))
+[GOOD] (assert (= (table0 #x0028) s67))
+[GOOD] (assert (= (table0 #x0029) s68))
+[GOOD] (assert (= (table0 #x002a) s69))
+[GOOD] (assert (= (table0 #x002b) s70))
+[GOOD] (assert (= (table0 #x002c) s71))
+[GOOD] (assert (= (table0 #x002d) s72))
+[GOOD] (assert (= (table0 #x002e) s73))
+[GOOD] (assert (= (table0 #x002f) s74))
+[GOOD] (assert (= (table0 #x0030) s75))
+[GOOD] (assert (= (table0 #x0031) s76))
+[GOOD] (assert (= (table0 #x0032) s77))
+[GOOD] (assert (= (table0 #x0033) s78))
+[GOOD] (assert (= (table0 #x0034) s79))
+[GOOD] (assert (= (table0 #x0035) s80))
+[GOOD] (assert (= (table0 #x0036) s81))
+[GOOD] (assert (= (table0 #x0037) s82))
+[GOOD] (assert (= (table0 #x0038) s83))
+[GOOD] (assert (= (table0 #x0039) s84))
+[GOOD] (assert (= (table0 #x003a) s85))
+[GOOD] (assert (= (table0 #x003b) s86))
+[GOOD] (assert (= (table0 #x003c) s87))
+[GOOD] (assert (= (table0 #x003d) s88))
+[GOOD] (assert (= (table0 #x003e) s89))
+[GOOD] (assert (= (table0 #x003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word32.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_right 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_right 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_right 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_right 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_right 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_right 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_right 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_right 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_right 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_right 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_right 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_right 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_right 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_right 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_right 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_right 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_right 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_right 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_right 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_right 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_right 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_right 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_right 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_right 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_right 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_right 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_right 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_right 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_right 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_right 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_right 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_right 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_right 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_right 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_right 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_right 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_right 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x00000040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s17))
+[GOOD] (assert (= (table0 #x00000002) s29))
+[GOOD] (assert (= (table0 #x00000003) s30))
+[GOOD] (assert (= (table0 #x00000004) s31))
+[GOOD] (assert (= (table0 #x00000005) s32))
+[GOOD] (assert (= (table0 #x00000006) s33))
+[GOOD] (assert (= (table0 #x00000007) s34))
+[GOOD] (assert (= (table0 #x00000008) s35))
+[GOOD] (assert (= (table0 #x00000009) s36))
+[GOOD] (assert (= (table0 #x0000000a) s37))
+[GOOD] (assert (= (table0 #x0000000b) s38))
+[GOOD] (assert (= (table0 #x0000000c) s39))
+[GOOD] (assert (= (table0 #x0000000d) s40))
+[GOOD] (assert (= (table0 #x0000000e) s41))
+[GOOD] (assert (= (table0 #x0000000f) s42))
+[GOOD] (assert (= (table0 #x00000010) s43))
+[GOOD] (assert (= (table0 #x00000011) s44))
+[GOOD] (assert (= (table0 #x00000012) s45))
+[GOOD] (assert (= (table0 #x00000013) s46))
+[GOOD] (assert (= (table0 #x00000014) s47))
+[GOOD] (assert (= (table0 #x00000015) s48))
+[GOOD] (assert (= (table0 #x00000016) s49))
+[GOOD] (assert (= (table0 #x00000017) s50))
+[GOOD] (assert (= (table0 #x00000018) s51))
+[GOOD] (assert (= (table0 #x00000019) s52))
+[GOOD] (assert (= (table0 #x0000001a) s53))
+[GOOD] (assert (= (table0 #x0000001b) s54))
+[GOOD] (assert (= (table0 #x0000001c) s55))
+[GOOD] (assert (= (table0 #x0000001d) s56))
+[GOOD] (assert (= (table0 #x0000001e) s57))
+[GOOD] (assert (= (table0 #x0000001f) s58))
+[GOOD] (assert (= (table0 #x00000020) s59))
+[GOOD] (assert (= (table0 #x00000021) s60))
+[GOOD] (assert (= (table0 #x00000022) s61))
+[GOOD] (assert (= (table0 #x00000023) s62))
+[GOOD] (assert (= (table0 #x00000024) s63))
+[GOOD] (assert (= (table0 #x00000025) s64))
+[GOOD] (assert (= (table0 #x00000026) s65))
+[GOOD] (assert (= (table0 #x00000027) s66))
+[GOOD] (assert (= (table0 #x00000028) s67))
+[GOOD] (assert (= (table0 #x00000029) s68))
+[GOOD] (assert (= (table0 #x0000002a) s69))
+[GOOD] (assert (= (table0 #x0000002b) s70))
+[GOOD] (assert (= (table0 #x0000002c) s71))
+[GOOD] (assert (= (table0 #x0000002d) s72))
+[GOOD] (assert (= (table0 #x0000002e) s73))
+[GOOD] (assert (= (table0 #x0000002f) s74))
+[GOOD] (assert (= (table0 #x00000030) s75))
+[GOOD] (assert (= (table0 #x00000031) s76))
+[GOOD] (assert (= (table0 #x00000032) s77))
+[GOOD] (assert (= (table0 #x00000033) s78))
+[GOOD] (assert (= (table0 #x00000034) s79))
+[GOOD] (assert (= (table0 #x00000035) s80))
+[GOOD] (assert (= (table0 #x00000036) s81))
+[GOOD] (assert (= (table0 #x00000037) s82))
+[GOOD] (assert (= (table0 #x00000038) s83))
+[GOOD] (assert (= (table0 #x00000039) s84))
+[GOOD] (assert (= (table0 #x0000003a) s85))
+[GOOD] (assert (= (table0 #x0000003b) s86))
+[GOOD] (assert (= (table0 #x0000003c) s87))
+[GOOD] (assert (= (table0 #x0000003d) s88))
+[GOOD] (assert (= (table0 #x0000003e) s89))
+[GOOD] (assert (= (table0 #x0000003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word64.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000040)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_right 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_right 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_right 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_right 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_right 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_right 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_right 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_right 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_right 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_right 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_right 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_right 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_right 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_right 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_right 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_right 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_right 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_right 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_right 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_right 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_right 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_right 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_right 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_right 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_right 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_right 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_right 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_right 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_right 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_right 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_right 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_right 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_right 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_right 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_right 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_right 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_right 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x0000000000000040 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s17))
+[GOOD] (assert (= (table0 #x0000000000000002) s29))
+[GOOD] (assert (= (table0 #x0000000000000003) s30))
+[GOOD] (assert (= (table0 #x0000000000000004) s31))
+[GOOD] (assert (= (table0 #x0000000000000005) s32))
+[GOOD] (assert (= (table0 #x0000000000000006) s33))
+[GOOD] (assert (= (table0 #x0000000000000007) s34))
+[GOOD] (assert (= (table0 #x0000000000000008) s35))
+[GOOD] (assert (= (table0 #x0000000000000009) s36))
+[GOOD] (assert (= (table0 #x000000000000000a) s37))
+[GOOD] (assert (= (table0 #x000000000000000b) s38))
+[GOOD] (assert (= (table0 #x000000000000000c) s39))
+[GOOD] (assert (= (table0 #x000000000000000d) s40))
+[GOOD] (assert (= (table0 #x000000000000000e) s41))
+[GOOD] (assert (= (table0 #x000000000000000f) s42))
+[GOOD] (assert (= (table0 #x0000000000000010) s43))
+[GOOD] (assert (= (table0 #x0000000000000011) s44))
+[GOOD] (assert (= (table0 #x0000000000000012) s45))
+[GOOD] (assert (= (table0 #x0000000000000013) s46))
+[GOOD] (assert (= (table0 #x0000000000000014) s47))
+[GOOD] (assert (= (table0 #x0000000000000015) s48))
+[GOOD] (assert (= (table0 #x0000000000000016) s49))
+[GOOD] (assert (= (table0 #x0000000000000017) s50))
+[GOOD] (assert (= (table0 #x0000000000000018) s51))
+[GOOD] (assert (= (table0 #x0000000000000019) s52))
+[GOOD] (assert (= (table0 #x000000000000001a) s53))
+[GOOD] (assert (= (table0 #x000000000000001b) s54))
+[GOOD] (assert (= (table0 #x000000000000001c) s55))
+[GOOD] (assert (= (table0 #x000000000000001d) s56))
+[GOOD] (assert (= (table0 #x000000000000001e) s57))
+[GOOD] (assert (= (table0 #x000000000000001f) s58))
+[GOOD] (assert (= (table0 #x0000000000000020) s59))
+[GOOD] (assert (= (table0 #x0000000000000021) s60))
+[GOOD] (assert (= (table0 #x0000000000000022) s61))
+[GOOD] (assert (= (table0 #x0000000000000023) s62))
+[GOOD] (assert (= (table0 #x0000000000000024) s63))
+[GOOD] (assert (= (table0 #x0000000000000025) s64))
+[GOOD] (assert (= (table0 #x0000000000000026) s65))
+[GOOD] (assert (= (table0 #x0000000000000027) s66))
+[GOOD] (assert (= (table0 #x0000000000000028) s67))
+[GOOD] (assert (= (table0 #x0000000000000029) s68))
+[GOOD] (assert (= (table0 #x000000000000002a) s69))
+[GOOD] (assert (= (table0 #x000000000000002b) s70))
+[GOOD] (assert (= (table0 #x000000000000002c) s71))
+[GOOD] (assert (= (table0 #x000000000000002d) s72))
+[GOOD] (assert (= (table0 #x000000000000002e) s73))
+[GOOD] (assert (= (table0 #x000000000000002f) s74))
+[GOOD] (assert (= (table0 #x0000000000000030) s75))
+[GOOD] (assert (= (table0 #x0000000000000031) s76))
+[GOOD] (assert (= (table0 #x0000000000000032) s77))
+[GOOD] (assert (= (table0 #x0000000000000033) s78))
+[GOOD] (assert (= (table0 #x0000000000000034) s79))
+[GOOD] (assert (= (table0 #x0000000000000035) s80))
+[GOOD] (assert (= (table0 #x0000000000000036) s81))
+[GOOD] (assert (= (table0 #x0000000000000037) s82))
+[GOOD] (assert (= (table0 #x0000000000000038) s83))
+[GOOD] (assert (= (table0 #x0000000000000039) s84))
+[GOOD] (assert (= (table0 #x000000000000003a) s85))
+[GOOD] (assert (= (table0 #x000000000000003b) s86))
+[GOOD] (assert (= (table0 #x000000000000003c) s87))
+[GOOD] (assert (= (table0 #x000000000000003d) s88))
+[GOOD] (assert (= (table0 #x000000000000003e) s89))
+[GOOD] (assert (= (table0 #x000000000000003f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word64_Word8.gold
@@ -0,0 +1,187 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x40)
+[GOOD] (define-fun s91 () (_ BitVec 64) #x0000000000000000)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 64))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 64))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 5 5) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 4 4) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 3 3) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s12 () Bool (distinct s5 s11))
+[GOOD] (define-fun s13 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s14 () Bool (distinct s5 s13))
+[GOOD] (define-fun s15 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s16 () Bool (distinct s5 s15))
+[GOOD] (define-fun s17 () (_ BitVec 64) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s18 () (_ BitVec 64) (ite s16 s17 s0))
+[GOOD] (define-fun s19 () (_ BitVec 64) ((_ rotate_right 2) s18))
+[GOOD] (define-fun s20 () (_ BitVec 64) (ite s14 s19 s18))
+[GOOD] (define-fun s21 () (_ BitVec 64) ((_ rotate_right 4) s20))
+[GOOD] (define-fun s22 () (_ BitVec 64) (ite s12 s21 s20))
+[GOOD] (define-fun s23 () (_ BitVec 64) ((_ rotate_right 8) s22))
+[GOOD] (define-fun s24 () (_ BitVec 64) (ite s10 s23 s22))
+[GOOD] (define-fun s25 () (_ BitVec 64) ((_ rotate_right 16) s24))
+[GOOD] (define-fun s26 () (_ BitVec 64) (ite s8 s25 s24))
+[GOOD] (define-fun s27 () (_ BitVec 64) ((_ rotate_right 32) s26))
+[GOOD] (define-fun s28 () (_ BitVec 64) (ite s6 s27 s26))
+[GOOD] (define-fun s29 () (_ BitVec 64) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s30 () (_ BitVec 64) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s31 () (_ BitVec 64) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s32 () (_ BitVec 64) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s33 () (_ BitVec 64) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s34 () (_ BitVec 64) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s35 () (_ BitVec 64) ((_ rotate_right 8) s0))
+[GOOD] (define-fun s36 () (_ BitVec 64) ((_ rotate_right 9) s0))
+[GOOD] (define-fun s37 () (_ BitVec 64) ((_ rotate_right 10) s0))
+[GOOD] (define-fun s38 () (_ BitVec 64) ((_ rotate_right 11) s0))
+[GOOD] (define-fun s39 () (_ BitVec 64) ((_ rotate_right 12) s0))
+[GOOD] (define-fun s40 () (_ BitVec 64) ((_ rotate_right 13) s0))
+[GOOD] (define-fun s41 () (_ BitVec 64) ((_ rotate_right 14) s0))
+[GOOD] (define-fun s42 () (_ BitVec 64) ((_ rotate_right 15) s0))
+[GOOD] (define-fun s43 () (_ BitVec 64) ((_ rotate_right 16) s0))
+[GOOD] (define-fun s44 () (_ BitVec 64) ((_ rotate_right 17) s0))
+[GOOD] (define-fun s45 () (_ BitVec 64) ((_ rotate_right 18) s0))
+[GOOD] (define-fun s46 () (_ BitVec 64) ((_ rotate_right 19) s0))
+[GOOD] (define-fun s47 () (_ BitVec 64) ((_ rotate_right 20) s0))
+[GOOD] (define-fun s48 () (_ BitVec 64) ((_ rotate_right 21) s0))
+[GOOD] (define-fun s49 () (_ BitVec 64) ((_ rotate_right 22) s0))
+[GOOD] (define-fun s50 () (_ BitVec 64) ((_ rotate_right 23) s0))
+[GOOD] (define-fun s51 () (_ BitVec 64) ((_ rotate_right 24) s0))
+[GOOD] (define-fun s52 () (_ BitVec 64) ((_ rotate_right 25) s0))
+[GOOD] (define-fun s53 () (_ BitVec 64) ((_ rotate_right 26) s0))
+[GOOD] (define-fun s54 () (_ BitVec 64) ((_ rotate_right 27) s0))
+[GOOD] (define-fun s55 () (_ BitVec 64) ((_ rotate_right 28) s0))
+[GOOD] (define-fun s56 () (_ BitVec 64) ((_ rotate_right 29) s0))
+[GOOD] (define-fun s57 () (_ BitVec 64) ((_ rotate_right 30) s0))
+[GOOD] (define-fun s58 () (_ BitVec 64) ((_ rotate_right 31) s0))
+[GOOD] (define-fun s59 () (_ BitVec 64) ((_ rotate_right 32) s0))
+[GOOD] (define-fun s60 () (_ BitVec 64) ((_ rotate_right 33) s0))
+[GOOD] (define-fun s61 () (_ BitVec 64) ((_ rotate_right 34) s0))
+[GOOD] (define-fun s62 () (_ BitVec 64) ((_ rotate_right 35) s0))
+[GOOD] (define-fun s63 () (_ BitVec 64) ((_ rotate_right 36) s0))
+[GOOD] (define-fun s64 () (_ BitVec 64) ((_ rotate_right 37) s0))
+[GOOD] (define-fun s65 () (_ BitVec 64) ((_ rotate_right 38) s0))
+[GOOD] (define-fun s66 () (_ BitVec 64) ((_ rotate_right 39) s0))
+[GOOD] (define-fun s67 () (_ BitVec 64) ((_ rotate_right 40) s0))
+[GOOD] (define-fun s68 () (_ BitVec 64) ((_ rotate_right 41) s0))
+[GOOD] (define-fun s69 () (_ BitVec 64) ((_ rotate_right 42) s0))
+[GOOD] (define-fun s70 () (_ BitVec 64) ((_ rotate_right 43) s0))
+[GOOD] (define-fun s71 () (_ BitVec 64) ((_ rotate_right 44) s0))
+[GOOD] (define-fun s72 () (_ BitVec 64) ((_ rotate_right 45) s0))
+[GOOD] (define-fun s73 () (_ BitVec 64) ((_ rotate_right 46) s0))
+[GOOD] (define-fun s74 () (_ BitVec 64) ((_ rotate_right 47) s0))
+[GOOD] (define-fun s75 () (_ BitVec 64) ((_ rotate_right 48) s0))
+[GOOD] (define-fun s76 () (_ BitVec 64) ((_ rotate_right 49) s0))
+[GOOD] (define-fun s77 () (_ BitVec 64) ((_ rotate_right 50) s0))
+[GOOD] (define-fun s78 () (_ BitVec 64) ((_ rotate_right 51) s0))
+[GOOD] (define-fun s79 () (_ BitVec 64) ((_ rotate_right 52) s0))
+[GOOD] (define-fun s80 () (_ BitVec 64) ((_ rotate_right 53) s0))
+[GOOD] (define-fun s81 () (_ BitVec 64) ((_ rotate_right 54) s0))
+[GOOD] (define-fun s82 () (_ BitVec 64) ((_ rotate_right 55) s0))
+[GOOD] (define-fun s83 () (_ BitVec 64) ((_ rotate_right 56) s0))
+[GOOD] (define-fun s84 () (_ BitVec 64) ((_ rotate_right 57) s0))
+[GOOD] (define-fun s85 () (_ BitVec 64) ((_ rotate_right 58) s0))
+[GOOD] (define-fun s86 () (_ BitVec 64) ((_ rotate_right 59) s0))
+[GOOD] (define-fun s87 () (_ BitVec 64) ((_ rotate_right 60) s0))
+[GOOD] (define-fun s88 () (_ BitVec 64) ((_ rotate_right 61) s0))
+[GOOD] (define-fun s89 () (_ BitVec 64) ((_ rotate_right 62) s0))
+[GOOD] (define-fun s90 () (_ BitVec 64) ((_ rotate_right 63) s0))
+[GOOD] (define-fun s92 () (_ BitVec 64) (ite (bvule #x40 s3) s91 (table0 s3)))
+[GOOD] (define-fun s93 () Bool (= s28 s92))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s17))
+[GOOD] (assert (= (table0 #x02) s29))
+[GOOD] (assert (= (table0 #x03) s30))
+[GOOD] (assert (= (table0 #x04) s31))
+[GOOD] (assert (= (table0 #x05) s32))
+[GOOD] (assert (= (table0 #x06) s33))
+[GOOD] (assert (= (table0 #x07) s34))
+[GOOD] (assert (= (table0 #x08) s35))
+[GOOD] (assert (= (table0 #x09) s36))
+[GOOD] (assert (= (table0 #x0a) s37))
+[GOOD] (assert (= (table0 #x0b) s38))
+[GOOD] (assert (= (table0 #x0c) s39))
+[GOOD] (assert (= (table0 #x0d) s40))
+[GOOD] (assert (= (table0 #x0e) s41))
+[GOOD] (assert (= (table0 #x0f) s42))
+[GOOD] (assert (= (table0 #x10) s43))
+[GOOD] (assert (= (table0 #x11) s44))
+[GOOD] (assert (= (table0 #x12) s45))
+[GOOD] (assert (= (table0 #x13) s46))
+[GOOD] (assert (= (table0 #x14) s47))
+[GOOD] (assert (= (table0 #x15) s48))
+[GOOD] (assert (= (table0 #x16) s49))
+[GOOD] (assert (= (table0 #x17) s50))
+[GOOD] (assert (= (table0 #x18) s51))
+[GOOD] (assert (= (table0 #x19) s52))
+[GOOD] (assert (= (table0 #x1a) s53))
+[GOOD] (assert (= (table0 #x1b) s54))
+[GOOD] (assert (= (table0 #x1c) s55))
+[GOOD] (assert (= (table0 #x1d) s56))
+[GOOD] (assert (= (table0 #x1e) s57))
+[GOOD] (assert (= (table0 #x1f) s58))
+[GOOD] (assert (= (table0 #x20) s59))
+[GOOD] (assert (= (table0 #x21) s60))
+[GOOD] (assert (= (table0 #x22) s61))
+[GOOD] (assert (= (table0 #x23) s62))
+[GOOD] (assert (= (table0 #x24) s63))
+[GOOD] (assert (= (table0 #x25) s64))
+[GOOD] (assert (= (table0 #x26) s65))
+[GOOD] (assert (= (table0 #x27) s66))
+[GOOD] (assert (= (table0 #x28) s67))
+[GOOD] (assert (= (table0 #x29) s68))
+[GOOD] (assert (= (table0 #x2a) s69))
+[GOOD] (assert (= (table0 #x2b) s70))
+[GOOD] (assert (= (table0 #x2c) s71))
+[GOOD] (assert (= (table0 #x2d) s72))
+[GOOD] (assert (= (table0 #x2e) s73))
+[GOOD] (assert (= (table0 #x2f) s74))
+[GOOD] (assert (= (table0 #x30) s75))
+[GOOD] (assert (= (table0 #x31) s76))
+[GOOD] (assert (= (table0 #x32) s77))
+[GOOD] (assert (= (table0 #x33) s78))
+[GOOD] (assert (= (table0 #x34) s79))
+[GOOD] (assert (= (table0 #x35) s80))
+[GOOD] (assert (= (table0 #x36) s81))
+[GOOD] (assert (= (table0 #x37) s82))
+[GOOD] (assert (= (table0 #x38) s83))
+[GOOD] (assert (= (table0 #x39) s84))
+[GOOD] (assert (= (table0 #x3a) s85))
+[GOOD] (assert (= (table0 #x3b) s86))
+[GOOD] (assert (= (table0 #x3c) s87))
+[GOOD] (assert (= (table0 #x3d) s88))
+[GOOD] (assert (= (table0 #x3e) s89))
+[GOOD] (assert (= (table0 #x3f) s90))
+[GOOD] (assert (not s93))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word16.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word16.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word16.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 16) #x0008)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 16))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 16)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 16) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_right 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_right 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x0008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x0000) s0))
+[GOOD] (assert (= (table0 #x0001) s11))
+[GOOD] (assert (= (table0 #x0002) s17))
+[GOOD] (assert (= (table0 #x0003) s18))
+[GOOD] (assert (= (table0 #x0004) s19))
+[GOOD] (assert (= (table0 #x0005) s20))
+[GOOD] (assert (= (table0 #x0006) s21))
+[GOOD] (assert (= (table0 #x0007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word32.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word32.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word32.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 32) #x00000008)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 32))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 32)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 32) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_right 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_right 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x00000008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x00000000) s0))
+[GOOD] (assert (= (table0 #x00000001) s11))
+[GOOD] (assert (= (table0 #x00000002) s17))
+[GOOD] (assert (= (table0 #x00000003) s18))
+[GOOD] (assert (= (table0 #x00000004) s19))
+[GOOD] (assert (= (table0 #x00000005) s20))
+[GOOD] (assert (= (table0 #x00000006) s21))
+[GOOD] (assert (= (table0 #x00000007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word64.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word64.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word64.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] (define-fun s2 () (_ BitVec 64) #x0000000000000008)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 64))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 64)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 64) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_right 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_right 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x0000000000000008 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x0000000000000000) s0))
+[GOOD] (assert (= (table0 #x0000000000000001) s11))
+[GOOD] (assert (= (table0 #x0000000000000002) s17))
+[GOOD] (assert (= (table0 #x0000000000000003) s18))
+[GOOD] (assert (= (table0 #x0000000000000004) s19))
+[GOOD] (assert (= (table0 #x0000000000000005) s20))
+[GOOD] (assert (= (table0 #x0000000000000006) s21))
+[GOOD] (assert (= (table0 #x0000000000000007) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word8.gold b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word8.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/barrelRotate_Right_Word8_Word8.gold
@@ -0,0 +1,63 @@
+** Calling: cvc4 --lang smt --incremental --interactive --no-interactive-prompt
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_UFBV)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () (_ BitVec 1) #b0)
+[GOOD] (define-fun s2 () (_ BitVec 8) #x08)
+[GOOD] (define-fun s23 () (_ BitVec 8) #x00)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8))
+[GOOD] (declare-fun s1 () (_ BitVec 8))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] (declare-fun table0 ((_ BitVec 8)) (_ BitVec 8))
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (_ BitVec 8) (bvurem s1 s2))
+[GOOD] (define-fun s4 () (_ BitVec 1) ((_ extract 2 2) s3))
+[GOOD] (define-fun s6 () Bool (distinct s4 s5))
+[GOOD] (define-fun s7 () (_ BitVec 1) ((_ extract 1 1) s3))
+[GOOD] (define-fun s8 () Bool (distinct s5 s7))
+[GOOD] (define-fun s9 () (_ BitVec 1) ((_ extract 0 0) s3))
+[GOOD] (define-fun s10 () Bool (distinct s5 s9))
+[GOOD] (define-fun s11 () (_ BitVec 8) ((_ rotate_right 1) s0))
+[GOOD] (define-fun s12 () (_ BitVec 8) (ite s10 s11 s0))
+[GOOD] (define-fun s13 () (_ BitVec 8) ((_ rotate_right 2) s12))
+[GOOD] (define-fun s14 () (_ BitVec 8) (ite s8 s13 s12))
+[GOOD] (define-fun s15 () (_ BitVec 8) ((_ rotate_right 4) s14))
+[GOOD] (define-fun s16 () (_ BitVec 8) (ite s6 s15 s14))
+[GOOD] (define-fun s17 () (_ BitVec 8) ((_ rotate_right 2) s0))
+[GOOD] (define-fun s18 () (_ BitVec 8) ((_ rotate_right 3) s0))
+[GOOD] (define-fun s19 () (_ BitVec 8) ((_ rotate_right 4) s0))
+[GOOD] (define-fun s20 () (_ BitVec 8) ((_ rotate_right 5) s0))
+[GOOD] (define-fun s21 () (_ BitVec 8) ((_ rotate_right 6) s0))
+[GOOD] (define-fun s22 () (_ BitVec 8) ((_ rotate_right 7) s0))
+[GOOD] (define-fun s24 () (_ BitVec 8) (ite (bvule #x08 s3) s23 (table0 s3)))
+[GOOD] (define-fun s25 () Bool (= s16 s24))
+[GOOD] (assert (= (table0 #x00) s0))
+[GOOD] (assert (= (table0 #x01) s11))
+[GOOD] (assert (= (table0 #x02) s17))
+[GOOD] (assert (= (table0 #x03) s18))
+[GOOD] (assert (= (table0 #x04) s19))
+[GOOD] (assert (= (table0 #x05) s20))
+[GOOD] (assert (= (table0 #x06) s21))
+[GOOD] (assert (= (table0 #x07) s22))
+[GOOD] (assert (not s25))
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : CVC4
+*** Exit code: ExitSuccess
+*** Std-out  : 
+
+FINAL:
+Q.E.D.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/concreteFoldl.gold b/SBVTestSuite/GoldFiles/concreteFoldl.gold
--- a/SBVTestSuite/GoldFiles/concreteFoldl.gold
+++ b/SBVTestSuite/GoldFiles/concreteFoldl.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/concreteFoldr.gold b/SBVTestSuite/GoldFiles/concreteFoldr.gold
--- a/SBVTestSuite/GoldFiles/concreteFoldr.gold
+++ b/SBVTestSuite/GoldFiles/concreteFoldr.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/concreteReverse.gold b/SBVTestSuite/GoldFiles/concreteReverse.gold
--- a/SBVTestSuite/GoldFiles/concreteReverse.gold
+++ b/SBVTestSuite/GoldFiles/concreteReverse.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/concreteSort.gold b/SBVTestSuite/GoldFiles/concreteSort.gold
--- a/SBVTestSuite/GoldFiles/concreteSort.gold
+++ b/SBVTestSuite/GoldFiles/concreteSort.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/exceptionLocal1.gold b/SBVTestSuite/GoldFiles/exceptionLocal1.gold
--- a/SBVTestSuite/GoldFiles/exceptionLocal1.gold
+++ b/SBVTestSuite/GoldFiles/exceptionLocal1.gold
@@ -7,6 +7,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 1) #b0)
 [GOOD] (define-fun s68 () (_ BitVec 32) #x00000001)
diff --git a/SBVTestSuite/GoldFiles/exceptionLocal2.gold b/SBVTestSuite/GoldFiles/exceptionLocal2.gold
--- a/SBVTestSuite/GoldFiles/exceptionLocal2.gold
+++ b/SBVTestSuite/GoldFiles/exceptionLocal2.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_LIA) ; NB. User specified.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () Real (/ 2.0 1.0))
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/floats_cgen.gold b/SBVTestSuite/GoldFiles/floats_cgen.gold
--- a/SBVTestSuite/GoldFiles/floats_cgen.gold
+++ b/SBVTestSuite/GoldFiles/floats_cgen.gold
@@ -314,14 +314,9 @@
 SInt8 fromFP_Float_ToInt8(const SFloat a)
 {
   const SFloat s0 = a;
-  const SBool  s1 = isnan(s0);
-  const SBool  s2 = isinf(s0);
-  const SBool  s3 = s1 || s2;
-  const SBool  s4 = !s3;
-  const SInt8  s6 = (SInt8) s0;
-  const SInt8  s8 = s4 ? s6 : 0;
+  const SInt8  s2 = (SInt8) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToInt8.c" ==================
 == BEGIN: "fromFP_Float_ToInt16.c" ================
@@ -332,14 +327,9 @@
 SInt16 fromFP_Float_ToInt16(const SFloat a)
 {
   const SFloat s0 = a;
-  const SBool  s1 = isnan(s0);
-  const SBool  s2 = isinf(s0);
-  const SBool  s3 = s1 || s2;
-  const SBool  s4 = !s3;
-  const SInt16 s6 = (SInt16) s0;
-  const SInt16 s8 = s4 ? s6 : 0x0000;
+  const SInt16 s2 = (SInt16) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToInt16.c" ==================
 == BEGIN: "fromFP_Float_ToInt32.c" ================
@@ -350,14 +340,9 @@
 SInt32 fromFP_Float_ToInt32(const SFloat a)
 {
   const SFloat s0 = a;
-  const SBool  s1 = isnan(s0);
-  const SBool  s2 = isinf(s0);
-  const SBool  s3 = s1 || s2;
-  const SBool  s4 = !s3;
-  const SInt32 s6 = (SInt32) s0;
-  const SInt32 s8 = s4 ? s6 : 0x00000000L;
+  const SInt32 s2 = (SInt32) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToInt32.c" ==================
 == BEGIN: "fromFP_Float_ToInt64.c" ================
@@ -368,14 +353,9 @@
 SInt64 fromFP_Float_ToInt64(const SFloat a)
 {
   const SFloat s0 = a;
-  const SBool  s1 = isnan(s0);
-  const SBool  s2 = isinf(s0);
-  const SBool  s3 = s1 || s2;
-  const SBool  s4 = !s3;
-  const SInt64 s6 = (SInt64) s0;
-  const SInt64 s8 = s4 ? s6 : 0x0000000000000000LL;
+  const SInt64 s2 = (SInt64) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToInt64.c" ==================
 == BEGIN: "fromFP_Float_ToWord8.c" ================
@@ -386,14 +366,9 @@
 SWord8 fromFP_Float_ToWord8(const SFloat a)
 {
   const SFloat s0 = a;
-  const SBool  s1 = isnan(s0);
-  const SBool  s2 = isinf(s0);
-  const SBool  s3 = s1 || s2;
-  const SBool  s4 = !s3;
-  const SWord8 s6 = (!isnan(s0) && signbit(s0)) ? (- ((SWord8) fabsf(s0))) : ((SWord8) s0);
-  const SWord8 s8 = s4 ? s6 : 0;
+  const SWord8 s2 = (SWord8) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToWord8.c" ==================
 == BEGIN: "fromFP_Float_ToWord16.c" ================
@@ -404,14 +379,9 @@
 SWord16 fromFP_Float_ToWord16(const SFloat a)
 {
   const SFloat  s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SWord16 s6 = (!isnan(s0) && signbit(s0)) ? (- ((SWord16) fabsf(s0))) : ((SWord16) s0);
-  const SWord16 s8 = s4 ? s6 : 0x0000U;
+  const SWord16 s2 = (SWord16) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToWord16.c" ==================
 == BEGIN: "fromFP_Float_ToWord32.c" ================
@@ -422,14 +392,9 @@
 SWord32 fromFP_Float_ToWord32(const SFloat a)
 {
   const SFloat  s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SWord32 s6 = (!isnan(s0) && signbit(s0)) ? (- ((SWord32) fabsf(s0))) : ((SWord32) s0);
-  const SWord32 s8 = s4 ? s6 : 0x00000000UL;
+  const SWord32 s2 = (SWord32) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToWord32.c" ==================
 == BEGIN: "fromFP_Float_ToWord64.c" ================
@@ -440,14 +405,9 @@
 SWord64 fromFP_Float_ToWord64(const SFloat a)
 {
   const SFloat  s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SWord64 s6 = (!isnan(s0) && signbit(s0)) ? (- ((SWord64) fabsf(s0))) : ((SWord64) s0);
-  const SWord64 s8 = s4 ? s6 : 0x0000000000000000ULL;
+  const SWord64 s2 = (SWord64) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToWord64.c" ==================
 == BEGIN: "fromFP_Float_ToFloat.c" ================
@@ -482,14 +442,9 @@
 SInteger fromFP_Float_ToInteger(const SFloat a)
 {
   const SFloat   s0 = a;
-  const SBool    s1 = isnan(s0);
-  const SBool    s2 = isinf(s0);
-  const SBool    s3 = s1 || s2;
-  const SBool    s4 = !s3;
-  const SInteger s6 = (SInteger) s0;
-  const SInteger s8 = s4 ? s6 : 0x0000000000000000LL;
+  const SInteger s2 = (SInteger) rintf(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToInteger.c" ==================
 == BEGIN: "fromFP_Float_ToReal.c" ================
@@ -500,14 +455,9 @@
 SReal fromFP_Float_ToReal(const SFloat a)
 {
   const SFloat s0 = a;
-  const SBool  s1 = isnan(s0);
-  const SBool  s2 = isinf(s0);
-  const SBool  s3 = s1 || s2;
-  const SBool  s4 = !s3;
-  const SReal  s6 = (SReal) s0;
-  const SReal  s8 = s4 ? s6 : 0.0L;
+  const SReal  s2 = (SReal) s0;
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_Float_ToReal.c" ==================
 == BEGIN: "fromFP_DoubleTo_Int8.c" ================
@@ -518,14 +468,9 @@
 SInt8 fromFP_DoubleTo_Int8(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SInt8   s6 = (SInt8) s0;
-  const SInt8   s8 = s4 ? s6 : 0;
+  const SInt8   s2 = (SInt8) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Int8.c" ==================
 == BEGIN: "fromFP_DoubleTo_Int16.c" ================
@@ -536,14 +481,9 @@
 SInt16 fromFP_DoubleTo_Int16(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SInt16  s6 = (SInt16) s0;
-  const SInt16  s8 = s4 ? s6 : 0x0000;
+  const SInt16  s2 = (SInt16) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Int16.c" ==================
 == BEGIN: "fromFP_DoubleTo_Int32.c" ================
@@ -554,14 +494,9 @@
 SInt32 fromFP_DoubleTo_Int32(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SInt32  s6 = (SInt32) s0;
-  const SInt32  s8 = s4 ? s6 : 0x00000000L;
+  const SInt32  s2 = (SInt32) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Int32.c" ==================
 == BEGIN: "fromFP_DoubleTo_Int64.c" ================
@@ -572,14 +507,9 @@
 SInt64 fromFP_DoubleTo_Int64(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SInt64  s6 = (SInt64) s0;
-  const SInt64  s8 = s4 ? s6 : 0x0000000000000000LL;
+  const SInt64  s2 = (SInt64) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Int64.c" ==================
 == BEGIN: "fromFP_DoubleTo_Word8.c" ================
@@ -590,14 +520,9 @@
 SWord8 fromFP_DoubleTo_Word8(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SWord8  s6 = (!isnan(s0) && signbit(s0)) ? (- ((SWord8) fabs(s0))) : ((SWord8) s0);
-  const SWord8  s8 = s4 ? s6 : 0;
+  const SWord8  s2 = (SWord8) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Word8.c" ==================
 == BEGIN: "fromFP_DoubleTo_Word16.c" ================
@@ -608,14 +533,9 @@
 SWord16 fromFP_DoubleTo_Word16(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SWord16 s6 = (!isnan(s0) && signbit(s0)) ? (- ((SWord16) fabs(s0))) : ((SWord16) s0);
-  const SWord16 s8 = s4 ? s6 : 0x0000U;
+  const SWord16 s2 = (SWord16) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Word16.c" ==================
 == BEGIN: "fromFP_DoubleTo_Word32.c" ================
@@ -626,14 +546,9 @@
 SWord32 fromFP_DoubleTo_Word32(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SWord32 s6 = (!isnan(s0) && signbit(s0)) ? (- ((SWord32) fabs(s0))) : ((SWord32) s0);
-  const SWord32 s8 = s4 ? s6 : 0x00000000UL;
+  const SWord32 s2 = (SWord32) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Word32.c" ==================
 == BEGIN: "fromFP_DoubleTo_Word64.c" ================
@@ -644,14 +559,9 @@
 SWord64 fromFP_DoubleTo_Word64(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SWord64 s6 = (!isnan(s0) && signbit(s0)) ? (- ((SWord64) fabs(s0))) : ((SWord64) s0);
-  const SWord64 s8 = s4 ? s6 : 0x0000000000000000ULL;
+  const SWord64 s2 = (SWord64) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Word64.c" ==================
 == BEGIN: "fromFP_DoubleTo_Float.c" ================
@@ -686,14 +596,9 @@
 SInteger fromFP_DoubleTo_Integer(const SDouble a)
 {
   const SDouble  s0 = a;
-  const SBool    s1 = isnan(s0);
-  const SBool    s2 = isinf(s0);
-  const SBool    s3 = s1 || s2;
-  const SBool    s4 = !s3;
-  const SInteger s6 = (SInteger) s0;
-  const SInteger s8 = s4 ? s6 : 0x0000000000000000LL;
+  const SInteger s2 = (SInteger) rint(s0);
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Integer.c" ==================
 == BEGIN: "fromFP_DoubleTo_Real.c" ================
@@ -704,14 +609,9 @@
 SReal fromFP_DoubleTo_Real(const SDouble a)
 {
   const SDouble s0 = a;
-  const SBool   s1 = isnan(s0);
-  const SBool   s2 = isinf(s0);
-  const SBool   s3 = s1 || s2;
-  const SBool   s4 = !s3;
-  const SReal   s6 = (SReal) s0;
-  const SReal   s8 = s4 ? s6 : 0.0L;
+  const SReal   s2 = (SReal) s0;
 
-  return s8;
+  return s2;
 }
 == END: "fromFP_DoubleTo_Real.c" ==================
 == BEGIN: "fromFP_SWord32_SFloat.c" ================
@@ -1049,8 +949,8 @@
 {
   const SFloat s0 = a;
   const SFloat s1 = b;
-  const SFloat s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0.0F : fminf(s0,
-                                                                                                                                s1);
+  const SFloat s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0x0p+0F /* 0.0F */ : fminf(s0,
+                                                                                                                                              s1);
 
   return s2;
 }
@@ -1064,8 +964,8 @@
 {
   const SDouble s0 = a;
   const SDouble s1 = b;
-  const SDouble s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0.0 : fmin(s0,
-                                                                                                                               s1);
+  const SDouble s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0x0p+0 /* 0.0 */ : fmin(s0,
+                                                                                                                                            s1);
 
   return s2;
 }
@@ -1079,8 +979,8 @@
 {
   const SFloat s0 = a;
   const SFloat s1 = b;
-  const SFloat s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0.0F : fmaxf(s0,
-                                                                                                                                s1);
+  const SFloat s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0x0p+0F /* 0.0F */ : fmaxf(s0,
+                                                                                                                                              s1);
 
   return s2;
 }
@@ -1094,8 +994,8 @@
 {
   const SDouble s0 = a;
   const SDouble s1 = b;
-  const SDouble s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0.0 : fmax(s0,
-                                                                                                                               s1);
+  const SDouble s2 = ((FP_ZERO == fpclassify(s0)) && (FP_ZERO == fpclassify(s1)) && (signbit(s0) != signbit(s1))) ? 0x0p+0 /* 0.0 */ : fmax(s0,
+                                                                                                                                            s1);
 
   return s2;
 }
@@ -1461,644 +1361,662 @@
 {
   const SFloat __result = toFP_Int8_ToFloat(42);
 
-  printf("toFP_Int8_ToFloat(42) = %.6g\n", __result);
+  printf("toFP_Int8_ToFloat(42) = %a\n", __result);
 }
 
 void toFP_Int16_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Int16_ToFloat(0x002a);
 
-  printf("toFP_Int16_ToFloat(0x002a) = %.6g\n", __result);
+  printf("toFP_Int16_ToFloat(0x002a) = %a\n", __result);
 }
 
 void toFP_Int32_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Int32_ToFloat(0x0000002aL);
 
-  printf("toFP_Int32_ToFloat(0x0000002aL) = %.6g\n", __result);
+  printf("toFP_Int32_ToFloat(0x0000002aL) = %a\n", __result);
 }
 
 void toFP_Int64_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Int64_ToFloat(0x000000000000002aLL);
 
-  printf("toFP_Int64_ToFloat(0x000000000000002aLL) = %.6g\n", __result);
+  printf("toFP_Int64_ToFloat(0x000000000000002aLL) = %a\n", __result);
 }
 
 void toFP_Word8_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Word8_ToFloat(42);
 
-  printf("toFP_Word8_ToFloat(42) = %.6g\n", __result);
+  printf("toFP_Word8_ToFloat(42) = %a\n", __result);
 }
 
 void toFP_Word16_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Word16_ToFloat(0x002aU);
 
-  printf("toFP_Word16_ToFloat(0x002aU) = %.6g\n", __result);
+  printf("toFP_Word16_ToFloat(0x002aU) = %a\n", __result);
 }
 
 void toFP_Word32_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Word32_ToFloat(0x0000002aUL);
 
-  printf("toFP_Word32_ToFloat(0x0000002aUL) = %.6g\n", __result);
+  printf("toFP_Word32_ToFloat(0x0000002aUL) = %a\n", __result);
 }
 
 void toFP_Word64_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Word64_ToFloat(0x000000000000002aULL);
 
-  printf("toFP_Word64_ToFloat(0x000000000000002aULL) = %.6g\n", __result);
+  printf("toFP_Word64_ToFloat(0x000000000000002aULL) = %a\n", __result);
 }
 
 void toFP_Float_ToFloat_driver(void)
 {
-  const SFloat __result = toFP_Float_ToFloat(42.0F);
+  const SFloat __result = toFP_Float_ToFloat(0x1.5p5F /* 42.0F */);
 
-  printf("toFP_Float_ToFloat(42.0F) = %.6g\n", __result);
+  printf("toFP_Float_ToFloat(0x1.5p5F /* 42.0F */) = %a\n", __result);
 }
 
 void toFP_Double_ToFloat_driver(void)
 {
-  const SFloat __result = toFP_Double_ToFloat(42.0);
+  const SFloat __result = toFP_Double_ToFloat(0x1.5p5 /* 42.0 */);
 
-  printf("toFP_Double_ToFloat(42.0) = %.6g\n", __result);
+  printf("toFP_Double_ToFloat(0x1.5p5 /* 42.0 */) = %a\n", __result);
 }
 
 void toFP_Integer_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Integer_ToFloat(0x000000000000002aLL);
 
-  printf("toFP_Integer_ToFloat(0x000000000000002aLL) = %.6g\n", __result);
+  printf("toFP_Integer_ToFloat(0x000000000000002aLL) = %a\n", __result);
 }
 
 void toFP_Real_ToFloat_driver(void)
 {
   const SFloat __result = toFP_Real_ToFloat(42.0L);
 
-  printf("toFP_Real_ToFloat(42.0L) = %.6g\n", __result);
+  printf("toFP_Real_ToFloat(42.0L) = %a\n", __result);
 }
 
 void toFP_Int8_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Int8_ToDouble(42);
 
-  printf("toFP_Int8_ToDouble(42) = %.15g\n", __result);
+  printf("toFP_Int8_ToDouble(42) = %a\n", __result);
 }
 
 void toFP_Int16_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Int16_ToDouble(0x002a);
 
-  printf("toFP_Int16_ToDouble(0x002a) = %.15g\n", __result);
+  printf("toFP_Int16_ToDouble(0x002a) = %a\n", __result);
 }
 
 void toFP_Int32_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Int32_ToDouble(0x0000002aL);
 
-  printf("toFP_Int32_ToDouble(0x0000002aL) = %.15g\n", __result);
+  printf("toFP_Int32_ToDouble(0x0000002aL) = %a\n", __result);
 }
 
 void toFP_Int64_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Int64_ToDouble(0x000000000000002aLL);
 
-  printf("toFP_Int64_ToDouble(0x000000000000002aLL) = %.15g\n", __result);
+  printf("toFP_Int64_ToDouble(0x000000000000002aLL) = %a\n", __result);
 }
 
 void toFP_Word8_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Word8_ToDouble(42);
 
-  printf("toFP_Word8_ToDouble(42) = %.15g\n", __result);
+  printf("toFP_Word8_ToDouble(42) = %a\n", __result);
 }
 
 void toFP_Word16_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Word16_ToDouble(0x002aU);
 
-  printf("toFP_Word16_ToDouble(0x002aU) = %.15g\n", __result);
+  printf("toFP_Word16_ToDouble(0x002aU) = %a\n", __result);
 }
 
 void toFP_Word32_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Word32_ToDouble(0x0000002aUL);
 
-  printf("toFP_Word32_ToDouble(0x0000002aUL) = %.15g\n", __result);
+  printf("toFP_Word32_ToDouble(0x0000002aUL) = %a\n", __result);
 }
 
 void toFP_Word64_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Word64_ToDouble(0x000000000000002aULL);
 
-  printf("toFP_Word64_ToDouble(0x000000000000002aULL) = %.15g\n", __result);
+  printf("toFP_Word64_ToDouble(0x000000000000002aULL) = %a\n", __result);
 }
 
 void toFP_Float_ToDouble_driver(void)
 {
-  const SDouble __result = toFP_Float_ToDouble(42.0F);
+  const SDouble __result = toFP_Float_ToDouble(0x1.5p5F /* 42.0F */);
 
-  printf("toFP_Float_ToDouble(42.0F) = %.15g\n", __result);
+  printf("toFP_Float_ToDouble(0x1.5p5F /* 42.0F */) = %a\n", __result);
 }
 
 void toFP_Double_ToDouble_driver(void)
 {
-  const SDouble __result = toFP_Double_ToDouble(42.0);
+  const SDouble __result = toFP_Double_ToDouble(0x1.5p5 /* 42.0 */);
 
-  printf("toFP_Double_ToDouble(42.0) = %.15g\n", __result);
+  printf("toFP_Double_ToDouble(0x1.5p5 /* 42.0 */) = %a\n", __result);
 }
 
 void toFP_Integer_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Integer_ToDouble(0x000000000000002aLL);
 
-  printf("toFP_Integer_ToDouble(0x000000000000002aLL) = %.15g\n", __result);
+  printf("toFP_Integer_ToDouble(0x000000000000002aLL) = %a\n", __result);
 }
 
 void toFP_Real_ToDouble_driver(void)
 {
   const SDouble __result = toFP_Real_ToDouble(42.0L);
 
-  printf("toFP_Real_ToDouble(42.0L) = %.15g\n", __result);
+  printf("toFP_Real_ToDouble(42.0L) = %a\n", __result);
 }
 
 void fromFP_Float_ToInt8_driver(void)
 {
-  const SInt8 __result = fromFP_Float_ToInt8(42.0F);
+  const SInt8 __result = fromFP_Float_ToInt8(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToInt8(42.0F) = %"PRId8"\n", __result);
+  printf("fromFP_Float_ToInt8(0x1.5p5F /* 42.0F */) = %"PRId8"\n", __result);
 }
 
 void fromFP_Float_ToInt16_driver(void)
 {
-  const SInt16 __result = fromFP_Float_ToInt16(42.0F);
+  const SInt16 __result = fromFP_Float_ToInt16(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToInt16(42.0F) = %"PRId16"\n", __result);
+  printf("fromFP_Float_ToInt16(0x1.5p5F /* 42.0F */) = %"PRId16"\n", __result);
 }
 
 void fromFP_Float_ToInt32_driver(void)
 {
-  const SInt32 __result = fromFP_Float_ToInt32(42.0F);
+  const SInt32 __result = fromFP_Float_ToInt32(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToInt32(42.0F) = %"PRId32"L\n", __result);
+  printf("fromFP_Float_ToInt32(0x1.5p5F /* 42.0F */) = %"PRId32"L\n", __result);
 }
 
 void fromFP_Float_ToInt64_driver(void)
 {
-  const SInt64 __result = fromFP_Float_ToInt64(42.0F);
+  const SInt64 __result = fromFP_Float_ToInt64(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToInt64(42.0F) = %"PRId64"LL\n", __result);
+  printf("fromFP_Float_ToInt64(0x1.5p5F /* 42.0F */) = %"PRId64"LL\n", __result);
 }
 
 void fromFP_Float_ToWord8_driver(void)
 {
-  const SWord8 __result = fromFP_Float_ToWord8(42.0F);
+  const SWord8 __result = fromFP_Float_ToWord8(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToWord8(42.0F) = %"PRIu8"\n", __result);
+  printf("fromFP_Float_ToWord8(0x1.5p5F /* 42.0F */) = %"PRIu8"\n", __result);
 }
 
 void fromFP_Float_ToWord16_driver(void)
 {
-  const SWord16 __result = fromFP_Float_ToWord16(42.0F);
+  const SWord16 __result = fromFP_Float_ToWord16(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToWord16(42.0F) = 0x%04"PRIx16"U\n", __result);
+  printf("fromFP_Float_ToWord16(0x1.5p5F /* 42.0F */) = 0x%04"PRIx16"U\n", __result);
 }
 
 void fromFP_Float_ToWord32_driver(void)
 {
-  const SWord32 __result = fromFP_Float_ToWord32(42.0F);
+  const SWord32 __result = fromFP_Float_ToWord32(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToWord32(42.0F) = 0x%08"PRIx32"UL\n", __result);
+  printf("fromFP_Float_ToWord32(0x1.5p5F /* 42.0F */) = 0x%08"PRIx32"UL\n", __result);
 }
 
 void fromFP_Float_ToWord64_driver(void)
 {
-  const SWord64 __result = fromFP_Float_ToWord64(42.0F);
+  const SWord64 __result = fromFP_Float_ToWord64(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToWord64(42.0F) = 0x%016"PRIx64"ULL\n", __result);
+  printf("fromFP_Float_ToWord64(0x1.5p5F /* 42.0F */) = 0x%016"PRIx64"ULL\n", __result);
 }
 
 void fromFP_Float_ToFloat_driver(void)
 {
-  const SFloat __result = fromFP_Float_ToFloat(42.0F);
+  const SFloat __result = fromFP_Float_ToFloat(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToFloat(42.0F) = %.6g\n", __result);
+  printf("fromFP_Float_ToFloat(0x1.5p5F /* 42.0F */) = %a\n", __result);
 }
 
 void fromFP_Float_ToDouble_driver(void)
 {
-  const SDouble __result = fromFP_Float_ToDouble(42.0F);
+  const SDouble __result = fromFP_Float_ToDouble(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToDouble(42.0F) = %.15g\n", __result);
+  printf("fromFP_Float_ToDouble(0x1.5p5F /* 42.0F */) = %a\n", __result);
 }
 
 void fromFP_Float_ToInteger_driver(void)
 {
-  const SInteger __result = fromFP_Float_ToInteger(42.0F);
+  const SInteger __result = fromFP_Float_ToInteger(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToInteger(42.0F) = %"PRId64"LL\n", __result);
+  printf("fromFP_Float_ToInteger(0x1.5p5F /* 42.0F */) = %"PRId64"LL\n", __result);
 }
 
 void fromFP_Float_ToReal_driver(void)
 {
-  const SReal __result = fromFP_Float_ToReal(42.0F);
+  const SReal __result = fromFP_Float_ToReal(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_Float_ToReal(42.0F) = %Lf\n", __result);
+  printf("fromFP_Float_ToReal(0x1.5p5F /* 42.0F */) = %Lf\n", __result);
 }
 
 void fromFP_DoubleTo_Int8_driver(void)
 {
-  const SInt8 __result = fromFP_DoubleTo_Int8(42.0);
+  const SInt8 __result = fromFP_DoubleTo_Int8(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Int8(42.0) = %"PRId8"\n", __result);
+  printf("fromFP_DoubleTo_Int8(0x1.5p5 /* 42.0 */) = %"PRId8"\n", __result);
 }
 
 void fromFP_DoubleTo_Int16_driver(void)
 {
-  const SInt16 __result = fromFP_DoubleTo_Int16(42.0);
+  const SInt16 __result = fromFP_DoubleTo_Int16(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Int16(42.0) = %"PRId16"\n", __result);
+  printf("fromFP_DoubleTo_Int16(0x1.5p5 /* 42.0 */) = %"PRId16"\n", __result);
 }
 
 void fromFP_DoubleTo_Int32_driver(void)
 {
-  const SInt32 __result = fromFP_DoubleTo_Int32(42.0);
+  const SInt32 __result = fromFP_DoubleTo_Int32(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Int32(42.0) = %"PRId32"L\n", __result);
+  printf("fromFP_DoubleTo_Int32(0x1.5p5 /* 42.0 */) = %"PRId32"L\n", __result);
 }
 
 void fromFP_DoubleTo_Int64_driver(void)
 {
-  const SInt64 __result = fromFP_DoubleTo_Int64(42.0);
+  const SInt64 __result = fromFP_DoubleTo_Int64(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Int64(42.0) = %"PRId64"LL\n", __result);
+  printf("fromFP_DoubleTo_Int64(0x1.5p5 /* 42.0 */) = %"PRId64"LL\n", __result);
 }
 
 void fromFP_DoubleTo_Word8_driver(void)
 {
-  const SWord8 __result = fromFP_DoubleTo_Word8(42.0);
+  const SWord8 __result = fromFP_DoubleTo_Word8(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Word8(42.0) = %"PRIu8"\n", __result);
+  printf("fromFP_DoubleTo_Word8(0x1.5p5 /* 42.0 */) = %"PRIu8"\n", __result);
 }
 
 void fromFP_DoubleTo_Word16_driver(void)
 {
-  const SWord16 __result = fromFP_DoubleTo_Word16(42.0);
+  const SWord16 __result = fromFP_DoubleTo_Word16(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Word16(42.0) = 0x%04"PRIx16"U\n", __result);
+  printf("fromFP_DoubleTo_Word16(0x1.5p5 /* 42.0 */) = 0x%04"PRIx16"U\n", __result);
 }
 
 void fromFP_DoubleTo_Word32_driver(void)
 {
-  const SWord32 __result = fromFP_DoubleTo_Word32(42.0);
+  const SWord32 __result = fromFP_DoubleTo_Word32(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Word32(42.0) = 0x%08"PRIx32"UL\n", __result);
+  printf("fromFP_DoubleTo_Word32(0x1.5p5 /* 42.0 */) = 0x%08"PRIx32"UL\n", __result);
 }
 
 void fromFP_DoubleTo_Word64_driver(void)
 {
-  const SWord64 __result = fromFP_DoubleTo_Word64(42.0);
+  const SWord64 __result = fromFP_DoubleTo_Word64(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Word64(42.0) = 0x%016"PRIx64"ULL\n", __result);
+  printf("fromFP_DoubleTo_Word64(0x1.5p5 /* 42.0 */) = 0x%016"PRIx64"ULL\n", __result);
 }
 
 void fromFP_DoubleTo_Float_driver(void)
 {
-  const SFloat __result = fromFP_DoubleTo_Float(42.0);
+  const SFloat __result = fromFP_DoubleTo_Float(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Float(42.0) = %.6g\n", __result);
+  printf("fromFP_DoubleTo_Float(0x1.5p5 /* 42.0 */) = %a\n", __result);
 }
 
 void fromFP_DoubleTo_Double_driver(void)
 {
-  const SDouble __result = fromFP_DoubleTo_Double(42.0);
+  const SDouble __result = fromFP_DoubleTo_Double(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Double(42.0) = %.15g\n", __result);
+  printf("fromFP_DoubleTo_Double(0x1.5p5 /* 42.0 */) = %a\n", __result);
 }
 
 void fromFP_DoubleTo_Integer_driver(void)
 {
-  const SInteger __result = fromFP_DoubleTo_Integer(42.0);
+  const SInteger __result = fromFP_DoubleTo_Integer(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Integer(42.0) = %"PRId64"LL\n", __result);
+  printf("fromFP_DoubleTo_Integer(0x1.5p5 /* 42.0 */) = %"PRId64"LL\n", __result);
 }
 
 void fromFP_DoubleTo_Real_driver(void)
 {
-  const SReal __result = fromFP_DoubleTo_Real(42.0);
+  const SReal __result = fromFP_DoubleTo_Real(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_DoubleTo_Real(42.0) = %Lf\n", __result);
+  printf("fromFP_DoubleTo_Real(0x1.5p5 /* 42.0 */) = %Lf\n", __result);
 }
 
 void fromFP_SWord32_SFloat_driver(void)
 {
   const SFloat __result = fromFP_SWord32_SFloat(0x0000002aUL);
 
-  printf("fromFP_SWord32_SFloat(0x0000002aUL) = %.6g\n", __result);
+  printf("fromFP_SWord32_SFloat(0x0000002aUL) = %a\n", __result);
 }
 
 void fromFP_SWord64_SDouble_driver(void)
 {
   const SDouble __result = fromFP_SWord64_SDouble(0x000000000000002aULL);
 
-  printf("fromFP_SWord64_SDouble(0x000000000000002aULL) = %.15g\n", __result);
+  printf("fromFP_SWord64_SDouble(0x000000000000002aULL) = %a\n", __result);
 }
 
 void fromFP_SFloat_SWord32_driver(void)
 {
-  const SWord32 __result = fromFP_SFloat_SWord32(42.0F);
+  const SWord32 __result = fromFP_SFloat_SWord32(0x1.5p5F /* 42.0F */);
 
-  printf("fromFP_SFloat_SWord32(42.0F) = 0x%08"PRIx32"UL\n", __result);
+  printf("fromFP_SFloat_SWord32(0x1.5p5F /* 42.0F */) = 0x%08"PRIx32"UL\n", __result);
 }
 
 void fromFP_SDouble_SWord64_driver(void)
 {
-  const SWord64 __result = fromFP_SDouble_SWord64(42.0);
+  const SWord64 __result = fromFP_SDouble_SWord64(0x1.5p5 /* 42.0 */);
 
-  printf("fromFP_SDouble_SWord64(42.0) = 0x%016"PRIx64"ULL\n", __result);
+  printf("fromFP_SDouble_SWord64(0x1.5p5 /* 42.0 */) = 0x%016"PRIx64"ULL\n", __result);
 }
 
 void f_FP_Abs_driver(void)
 {
-  const SFloat __result = f_FP_Abs(42.0F);
+  const SFloat __result = f_FP_Abs(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_Abs(42.0F) = %.6g\n", __result);
+  printf("f_FP_Abs(0x1.5p5F /* 42.0F */) = %a\n", __result);
 }
 
 void d_FP_Abs_driver(void)
 {
-  const SDouble __result = d_FP_Abs(42.0);
+  const SDouble __result = d_FP_Abs(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_Abs(42.0) = %.15g\n", __result);
+  printf("d_FP_Abs(0x1.5p5 /* 42.0 */) = %a\n", __result);
 }
 
 void f_FP_Neg_driver(void)
 {
-  const SFloat __result = f_FP_Neg(42.0F);
+  const SFloat __result = f_FP_Neg(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_Neg(42.0F) = %.6g\n", __result);
+  printf("f_FP_Neg(0x1.5p5F /* 42.0F */) = %a\n", __result);
 }
 
 void d_FP_Neg_driver(void)
 {
-  const SDouble __result = d_FP_Neg(42.0);
+  const SDouble __result = d_FP_Neg(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_Neg(42.0) = %.15g\n", __result);
+  printf("d_FP_Neg(0x1.5p5 /* 42.0 */) = %a\n", __result);
 }
 
 void f_FP_Add_driver(void)
 {
-  const SFloat __result = f_FP_Add(42.0F, 43.0F);
+  const SFloat __result = f_FP_Add(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
 
-  printf("f_FP_Add(42.0F, 43.0F) = %.6g\n", __result);
+  printf("f_FP_Add(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */) = %a\n", __result);
 }
 
 void d_FP_Add_driver(void)
 {
-  const SDouble __result = d_FP_Add(42.0, 43.0);
+  const SDouble __result = d_FP_Add(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
 
-  printf("d_FP_Add(42.0, 43.0) = %.15g\n", __result);
+  printf("d_FP_Add(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */) = %a\n", __result);
 }
 
 void f_FP_Sub_driver(void)
 {
-  const SFloat __result = f_FP_Sub(42.0F, 43.0F);
+  const SFloat __result = f_FP_Sub(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
 
-  printf("f_FP_Sub(42.0F, 43.0F) = %.6g\n", __result);
+  printf("f_FP_Sub(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */) = %a\n", __result);
 }
 
 void d_FP_Sub_driver(void)
 {
-  const SDouble __result = d_FP_Sub(42.0, 43.0);
+  const SDouble __result = d_FP_Sub(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
 
-  printf("d_FP_Sub(42.0, 43.0) = %.15g\n", __result);
+  printf("d_FP_Sub(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */) = %a\n", __result);
 }
 
 void f_FP_Mul_driver(void)
 {
-  const SFloat __result = f_FP_Mul(42.0F, 43.0F);
+  const SFloat __result = f_FP_Mul(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
 
-  printf("f_FP_Mul(42.0F, 43.0F) = %.6g\n", __result);
+  printf("f_FP_Mul(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */) = %a\n", __result);
 }
 
 void d_FP_Mul_driver(void)
 {
-  const SDouble __result = d_FP_Mul(42.0, 43.0);
+  const SDouble __result = d_FP_Mul(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
 
-  printf("d_FP_Mul(42.0, 43.0) = %.15g\n", __result);
+  printf("d_FP_Mul(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */) = %a\n", __result);
 }
 
 void f_FP_Div_driver(void)
 {
-  const SFloat __result = f_FP_Div(42.0F, 43.0F);
+  const SFloat __result = f_FP_Div(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
 
-  printf("f_FP_Div(42.0F, 43.0F) = %.6g\n", __result);
+  printf("f_FP_Div(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */) = %a\n", __result);
 }
 
 void d_FP_Div_driver(void)
 {
-  const SDouble __result = d_FP_Div(42.0, 43.0);
+  const SDouble __result = d_FP_Div(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
 
-  printf("d_FP_Div(42.0, 43.0) = %.15g\n", __result);
+  printf("d_FP_Div(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */) = %a\n", __result);
 }
 
 void f_FP_FMA_driver(void)
 {
-  const SFloat __result = f_FP_FMA(42.0F, 43.0F, 44.0F);
+  const SFloat __result = f_FP_FMA(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */, 0x1.6p5F /* 44.0F */);
 
-  printf("f_FP_FMA(42.0F, 43.0F, 44.0F) = %.6g\n", __result);
+  printf("f_FP_FMA(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */, 0x1.6p5F /* 44.0F */) = %a\n", __result);
 }
 
 void d_FP_FMA_driver(void)
 {
-  const SDouble __result = d_FP_FMA(42.0, 43.0, 44.0);
+  const SDouble __result = d_FP_FMA(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */, 0x1.6p5 /* 44.0 */);
 
-  printf("d_FP_FMA(42.0, 43.0, 44.0) = %.15g\n", __result);
+  printf("d_FP_FMA(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */, 0x1.6p5 /* 44.0 */) = %a\n", __result);
 }
 
 void f_FP_Sqrt_driver(void)
 {
-  const SFloat __result = f_FP_Sqrt(42.0F);
+  const SFloat __result = f_FP_Sqrt(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_Sqrt(42.0F) = %.6g\n", __result);
+  printf("f_FP_Sqrt(0x1.5p5F /* 42.0F */) = %a\n", __result);
 }
 
 void d_FP_Sqrt_driver(void)
 {
-  const SDouble __result = d_FP_Sqrt(42.0);
+  const SDouble __result = d_FP_Sqrt(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_Sqrt(42.0) = %.15g\n", __result);
+  printf("d_FP_Sqrt(0x1.5p5 /* 42.0 */) = %a\n", __result);
 }
 
 void f_FP_Rem_driver(void)
 {
-  const SFloat __result = f_FP_Rem(42.0F, 43.0F);
+  const SFloat __result = f_FP_Rem(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
 
-  printf("f_FP_Rem(42.0F, 43.0F) = %.6g\n", __result);
+  printf("f_FP_Rem(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */) = %a\n", __result);
 }
 
 void d_FP_Rem_driver(void)
 {
-  const SDouble __result = d_FP_Rem(42.0, 43.0);
+  const SDouble __result = d_FP_Rem(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
 
-  printf("d_FP_Rem(42.0, 43.0) = %.15g\n", __result);
+  printf("d_FP_Rem(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */) = %a\n", __result);
 }
 
 void f_FP_RoundToIntegral_driver(void)
 {
-  const SFloat __result = f_FP_RoundToIntegral(42.0F);
+  const SFloat __result = f_FP_RoundToIntegral(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_RoundToIntegral(42.0F) = %.6g\n", __result);
+  printf("f_FP_RoundToIntegral(0x1.5p5F /* 42.0F */) = %a\n", __result);
 }
 
 void d_FP_RoundToIntegral_driver(void)
 {
-  const SDouble __result = d_FP_RoundToIntegral(42.0);
+  const SDouble __result = d_FP_RoundToIntegral(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_RoundToIntegral(42.0) = %.15g\n", __result);
+  printf("d_FP_RoundToIntegral(0x1.5p5 /* 42.0 */) = %a\n", __result);
 }
 
 void f_FP_Min_driver(void)
 {
-  const SFloat __result = f_FP_Min(42.0F, 43.0F);
+  const SFloat __result = f_FP_Min(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
 
-  printf("f_FP_Min(42.0F, 43.0F) = %.6g\n", __result);
+  printf("f_FP_Min(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */) = %a\n", __result);
 }
 
 void d_FP_Min_driver(void)
 {
-  const SDouble __result = d_FP_Min(42.0, 43.0);
+  const SDouble __result = d_FP_Min(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
 
-  printf("d_FP_Min(42.0, 43.0) = %.15g\n", __result);
+  printf("d_FP_Min(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */) = %a\n", __result);
 }
 
 void f_FP_Max_driver(void)
 {
-  const SFloat __result = f_FP_Max(42.0F, 43.0F);
+  const SFloat __result = f_FP_Max(0x1.5p5F /* 42.0F */,
+                                   0x1.58p5F /* 43.0F */);
 
-  printf("f_FP_Max(42.0F, 43.0F) = %.6g\n", __result);
+  printf("f_FP_Max(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */) = %a\n", __result);
 }
 
 void d_FP_Max_driver(void)
 {
-  const SDouble __result = d_FP_Max(42.0, 43.0);
+  const SDouble __result = d_FP_Max(0x1.5p5 /* 42.0 */,
+                                    0x1.58p5 /* 43.0 */);
 
-  printf("d_FP_Max(42.0, 43.0) = %.15g\n", __result);
+  printf("d_FP_Max(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */) = %a\n", __result);
 }
 
 void f_FP_IsEqualObject_driver(void)
 {
-  const SBool __result = f_FP_IsEqualObject(42.0F, 43.0F);
+  const SBool __result = f_FP_IsEqualObject(0x1.5p5F /* 42.0F */,
+                                            0x1.58p5F /* 43.0F */);
 
-  printf("f_FP_IsEqualObject(42.0F, 43.0F) = %d\n", __result);
+  printf("f_FP_IsEqualObject(0x1.5p5F /* 42.0F */, 0x1.58p5F /* 43.0F */) = %d\n", __result);
 }
 
 void d_FP_IsEqualObject_driver(void)
 {
-  const SBool __result = d_FP_IsEqualObject(42.0, 43.0);
+  const SBool __result = d_FP_IsEqualObject(0x1.5p5 /* 42.0 */,
+                                            0x1.58p5 /* 43.0 */);
 
-  printf("d_FP_IsEqualObject(42.0, 43.0) = %d\n", __result);
+  printf("d_FP_IsEqualObject(0x1.5p5 /* 42.0 */, 0x1.58p5 /* 43.0 */) = %d\n", __result);
 }
 
 void f_FP_IsNormal_driver(void)
 {
-  const SBool __result = f_FP_IsNormal(42.0F);
+  const SBool __result = f_FP_IsNormal(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_IsNormal(42.0F) = %d\n", __result);
+  printf("f_FP_IsNormal(0x1.5p5F /* 42.0F */) = %d\n", __result);
 }
 
 void d_FP_IsNormal_driver(void)
 {
-  const SBool __result = d_FP_IsNormal(42.0);
+  const SBool __result = d_FP_IsNormal(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_IsNormal(42.0) = %d\n", __result);
+  printf("d_FP_IsNormal(0x1.5p5 /* 42.0 */) = %d\n", __result);
 }
 
 void f_FP_IsZero_driver(void)
 {
-  const SBool __result = f_FP_IsZero(42.0F);
+  const SBool __result = f_FP_IsZero(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_IsZero(42.0F) = %d\n", __result);
+  printf("f_FP_IsZero(0x1.5p5F /* 42.0F */) = %d\n", __result);
 }
 
 void d_FP_IsZero_driver(void)
 {
-  const SBool __result = d_FP_IsZero(42.0);
+  const SBool __result = d_FP_IsZero(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_IsZero(42.0) = %d\n", __result);
+  printf("d_FP_IsZero(0x1.5p5 /* 42.0 */) = %d\n", __result);
 }
 
 void f_FP_IsSubnormal_driver(void)
 {
-  const SBool __result = f_FP_IsSubnormal(42.0F);
+  const SBool __result = f_FP_IsSubnormal(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_IsSubnormal(42.0F) = %d\n", __result);
+  printf("f_FP_IsSubnormal(0x1.5p5F /* 42.0F */) = %d\n", __result);
 }
 
 void d_FP_IsSubnormal_driver(void)
 {
-  const SBool __result = d_FP_IsSubnormal(42.0);
+  const SBool __result = d_FP_IsSubnormal(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_IsSubnormal(42.0) = %d\n", __result);
+  printf("d_FP_IsSubnormal(0x1.5p5 /* 42.0 */) = %d\n", __result);
 }
 
 void f_FP_IsInfinite_driver(void)
 {
-  const SBool __result = f_FP_IsInfinite(42.0F);
+  const SBool __result = f_FP_IsInfinite(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_IsInfinite(42.0F) = %d\n", __result);
+  printf("f_FP_IsInfinite(0x1.5p5F /* 42.0F */) = %d\n", __result);
 }
 
 void d_FP_IsInfinite_driver(void)
 {
-  const SBool __result = d_FP_IsInfinite(42.0);
+  const SBool __result = d_FP_IsInfinite(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_IsInfinite(42.0) = %d\n", __result);
+  printf("d_FP_IsInfinite(0x1.5p5 /* 42.0 */) = %d\n", __result);
 }
 
 void f_FP_IsNaN_driver(void)
 {
-  const SBool __result = f_FP_IsNaN(42.0F);
+  const SBool __result = f_FP_IsNaN(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_IsNaN(42.0F) = %d\n", __result);
+  printf("f_FP_IsNaN(0x1.5p5F /* 42.0F */) = %d\n", __result);
 }
 
 void d_FP_IsNaN_driver(void)
 {
-  const SBool __result = d_FP_IsNaN(42.0);
+  const SBool __result = d_FP_IsNaN(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_IsNaN(42.0) = %d\n", __result);
+  printf("d_FP_IsNaN(0x1.5p5 /* 42.0 */) = %d\n", __result);
 }
 
 void f_FP_IsNegative_driver(void)
 {
-  const SBool __result = f_FP_IsNegative(42.0F);
+  const SBool __result = f_FP_IsNegative(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_IsNegative(42.0F) = %d\n", __result);
+  printf("f_FP_IsNegative(0x1.5p5F /* 42.0F */) = %d\n", __result);
 }
 
 void d_FP_IsNegative_driver(void)
 {
-  const SBool __result = d_FP_IsNegative(42.0);
+  const SBool __result = d_FP_IsNegative(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_IsNegative(42.0) = %d\n", __result);
+  printf("d_FP_IsNegative(0x1.5p5 /* 42.0 */) = %d\n", __result);
 }
 
 void f_FP_IsPositive_driver(void)
 {
-  const SBool __result = f_FP_IsPositive(42.0F);
+  const SBool __result = f_FP_IsPositive(0x1.5p5F /* 42.0F */);
 
-  printf("f_FP_IsPositive(42.0F) = %d\n", __result);
+  printf("f_FP_IsPositive(0x1.5p5F /* 42.0F */) = %d\n", __result);
 }
 
 void d_FP_IsPositive_driver(void)
 {
-  const SBool __result = d_FP_IsPositive(42.0);
+  const SBool __result = d_FP_IsPositive(0x1.5p5 /* 42.0 */);
 
-  printf("d_FP_IsPositive(42.0) = %d\n", __result);
+  printf("d_FP_IsPositive(0x1.5p5 /* 42.0 */) = %d\n", __result);
 }
 
 int main(void)
diff --git a/SBVTestSuite/GoldFiles/foldlABC1.gold b/SBVTestSuite/GoldFiles/foldlABC1.gold
--- a/SBVTestSuite/GoldFiles/foldlABC1.gold
+++ b/SBVTestSuite/GoldFiles/foldlABC1.gold
@@ -10,10 +10,10 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () Int 0)
-[GOOD] (define-fun s19 () Int 1)
-[GOOD] (define-fun s12 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s16 () Int 1)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
@@ -33,23 +33,22 @@
 [GOOD] (define-fun s9 () (Seq Int) (seq.unit s2))
 [GOOD] (define-fun s10 () (Seq Int) (seq.++ s8 s9))
 [GOOD] (define-fun s11 () (Seq Int) (seq.++ s7 s10))
-[GOOD] (define-fun s13 () Bool (= s11 s12))
+[GOOD] (define-fun s12 () Int (seq.len s11))
+[GOOD] (define-fun s13 () Bool (= s3 s12))
 [GOOD] (define-fun s15 () (Seq Int) (seq.unit s14))
-[GOOD] (define-fun s16 () Int (seq.len s11))
-[GOOD] (define-fun s17 () Bool (> s16 s3))
-[GOOD] (define-fun s18 () Bool (not s17))
-[GOOD] (define-fun s20 () (Seq Int) (seq.extract s11 s3 s19))
-[GOOD] (define-fun s21 () Bool (= s15 s20))
-[GOOD] (define-fun s22 () Bool (or s18 s21))
-[GOOD] (define-fun s23 () Int (ite s13 s3 s14))
-[GOOD] (define-fun s24 () Int (+ s0 s1))
-[GOOD] (define-fun s25 () Int (+ s2 s24))
-[GOOD] (define-fun s26 () Bool (= s23 s25))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s11 s3 s16))
+[GOOD] (define-fun s18 () Bool (= s15 s17))
+[GOOD] (define-fun s19 () Bool (<= s12 s3))
+[GOOD] (define-fun s20 () Bool (or s18 s19))
+[GOOD] (define-fun s21 () Int (ite s13 s3 s14))
+[GOOD] (define-fun s22 () Int (+ s0 s1))
+[GOOD] (define-fun s23 () Int (+ s2 s22))
+[GOOD] (define-fun s24 () Bool (= s21 s23))
 [GOOD] (assert s4)
 [GOOD] (assert s5)
 [GOOD] (assert s6)
-[GOOD] (assert s22)
-[GOOD] (assert s26)
+[GOOD] (assert s20)
+[GOOD] (assert s24)
 [SEND] (check-sat)
 [RECV] unsat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/foldlABC2.gold b/SBVTestSuite/GoldFiles/foldlABC2.gold
--- a/SBVTestSuite/GoldFiles/foldlABC2.gold
+++ b/SBVTestSuite/GoldFiles/foldlABC2.gold
@@ -10,16 +10,16 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () Int 0)
-[GOOD] (define-fun s19 () Int 1)
-[GOOD] (define-fun s12 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s16 () Int 1)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
 [GOOD] (declare-fun s2 () Int) ; tracks user variable "c"
 [GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
-[GOOD] (declare-fun s26 () Int) ; tracks user variable "__internal_sbv_s26"
+[GOOD] (declare-fun s25 () Int) ; tracks user variable "__internal_sbv_s25"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -34,36 +34,34 @@
 [GOOD] (define-fun s9 () (Seq Int) (seq.unit s2))
 [GOOD] (define-fun s10 () (Seq Int) (seq.++ s8 s9))
 [GOOD] (define-fun s11 () (Seq Int) (seq.++ s7 s10))
-[GOOD] (define-fun s13 () Bool (= s11 s12))
+[GOOD] (define-fun s12 () Int (seq.len s11))
+[GOOD] (define-fun s13 () Bool (= s3 s12))
 [GOOD] (define-fun s15 () (Seq Int) (seq.unit s14))
-[GOOD] (define-fun s16 () Int (seq.len s11))
-[GOOD] (define-fun s17 () Bool (> s16 s3))
-[GOOD] (define-fun s18 () Bool (not s17))
-[GOOD] (define-fun s20 () (Seq Int) (seq.extract s11 s3 s19))
-[GOOD] (define-fun s21 () Bool (= s15 s20))
-[GOOD] (define-fun s22 () Bool (or s18 s21))
-[GOOD] (define-fun s23 () Int (- s16 s19))
-[GOOD] (define-fun s24 () (Seq Int) (seq.extract s11 s19 s23))
-[GOOD] (define-fun s25 () Bool (= s12 s24))
-[GOOD] (define-fun s27 () (Seq Int) (seq.unit s26))
-[GOOD] (define-fun s28 () Int (seq.len s24))
-[GOOD] (define-fun s29 () Bool (> s28 s3))
-[GOOD] (define-fun s30 () Bool (not s29))
-[GOOD] (define-fun s31 () (Seq Int) (seq.extract s24 s3 s19))
-[GOOD] (define-fun s32 () Bool (= s27 s31))
-[GOOD] (define-fun s33 () Bool (or s30 s32))
-[GOOD] (define-fun s34 () Int (ite s25 s3 s26))
-[GOOD] (define-fun s35 () Int (+ s14 s34))
-[GOOD] (define-fun s36 () Int (ite s13 s3 s35))
-[GOOD] (define-fun s37 () Int (+ s0 s1))
-[GOOD] (define-fun s38 () Int (+ s2 s37))
-[GOOD] (define-fun s39 () Bool (= s36 s38))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s11 s3 s16))
+[GOOD] (define-fun s18 () Bool (= s15 s17))
+[GOOD] (define-fun s19 () Bool (<= s12 s3))
+[GOOD] (define-fun s20 () Bool (or s18 s19))
+[GOOD] (define-fun s21 () Int (- s12 s16))
+[GOOD] (define-fun s22 () (Seq Int) (seq.extract s11 s16 s21))
+[GOOD] (define-fun s23 () Int (seq.len s22))
+[GOOD] (define-fun s24 () Bool (= s3 s23))
+[GOOD] (define-fun s26 () (Seq Int) (seq.unit s25))
+[GOOD] (define-fun s27 () (Seq Int) (seq.extract s22 s3 s16))
+[GOOD] (define-fun s28 () Bool (= s26 s27))
+[GOOD] (define-fun s29 () Bool (<= s23 s3))
+[GOOD] (define-fun s30 () Bool (or s28 s29))
+[GOOD] (define-fun s31 () Int (ite s24 s3 s25))
+[GOOD] (define-fun s32 () Int (+ s14 s31))
+[GOOD] (define-fun s33 () Int (ite s13 s3 s32))
+[GOOD] (define-fun s34 () Int (+ s0 s1))
+[GOOD] (define-fun s35 () Int (+ s2 s34))
+[GOOD] (define-fun s36 () Bool (= s33 s35))
 [GOOD] (assert s4)
 [GOOD] (assert s5)
 [GOOD] (assert s6)
-[GOOD] (assert s22)
-[GOOD] (assert s33)
-[GOOD] (assert s39)
+[GOOD] (assert s20)
+[GOOD] (assert s30)
+[GOOD] (assert s36)
 [SEND] (check-sat)
 [RECV] unsat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/foldlABC3.gold b/SBVTestSuite/GoldFiles/foldlABC3.gold
--- a/SBVTestSuite/GoldFiles/foldlABC3.gold
+++ b/SBVTestSuite/GoldFiles/foldlABC3.gold
@@ -10,17 +10,17 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () Int 0)
-[GOOD] (define-fun s19 () Int 1)
-[GOOD] (define-fun s12 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s16 () Int 1)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
 [GOOD] (declare-fun s2 () Int) ; tracks user variable "c"
 [GOOD] (declare-fun s14 () Int) ; tracks user variable "__internal_sbv_s14"
-[GOOD] (declare-fun s26 () Int) ; tracks user variable "__internal_sbv_s26"
-[GOOD] (declare-fun s37 () Int) ; tracks user variable "__internal_sbv_s37"
+[GOOD] (declare-fun s25 () Int) ; tracks user variable "__internal_sbv_s25"
+[GOOD] (declare-fun s35 () Int) ; tracks user variable "__internal_sbv_s35"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -35,49 +35,46 @@
 [GOOD] (define-fun s9 () (Seq Int) (seq.unit s2))
 [GOOD] (define-fun s10 () (Seq Int) (seq.++ s8 s9))
 [GOOD] (define-fun s11 () (Seq Int) (seq.++ s7 s10))
-[GOOD] (define-fun s13 () Bool (= s11 s12))
+[GOOD] (define-fun s12 () Int (seq.len s11))
+[GOOD] (define-fun s13 () Bool (= s3 s12))
 [GOOD] (define-fun s15 () (Seq Int) (seq.unit s14))
-[GOOD] (define-fun s16 () Int (seq.len s11))
-[GOOD] (define-fun s17 () Bool (> s16 s3))
-[GOOD] (define-fun s18 () Bool (not s17))
-[GOOD] (define-fun s20 () (Seq Int) (seq.extract s11 s3 s19))
-[GOOD] (define-fun s21 () Bool (= s15 s20))
-[GOOD] (define-fun s22 () Bool (or s18 s21))
-[GOOD] (define-fun s23 () Int (- s16 s19))
-[GOOD] (define-fun s24 () (Seq Int) (seq.extract s11 s19 s23))
-[GOOD] (define-fun s25 () Bool (= s12 s24))
-[GOOD] (define-fun s27 () (Seq Int) (seq.unit s26))
-[GOOD] (define-fun s28 () Int (seq.len s24))
-[GOOD] (define-fun s29 () Bool (> s28 s3))
-[GOOD] (define-fun s30 () Bool (not s29))
-[GOOD] (define-fun s31 () (Seq Int) (seq.extract s24 s3 s19))
-[GOOD] (define-fun s32 () Bool (= s27 s31))
-[GOOD] (define-fun s33 () Bool (or s30 s32))
-[GOOD] (define-fun s34 () Int (- s28 s19))
-[GOOD] (define-fun s35 () (Seq Int) (seq.extract s24 s19 s34))
-[GOOD] (define-fun s36 () Bool (= s12 s35))
-[GOOD] (define-fun s38 () (Seq Int) (seq.unit s37))
-[GOOD] (define-fun s39 () Int (seq.len s35))
-[GOOD] (define-fun s40 () Bool (> s39 s3))
-[GOOD] (define-fun s41 () Bool (not s40))
-[GOOD] (define-fun s42 () (Seq Int) (seq.extract s35 s3 s19))
-[GOOD] (define-fun s43 () Bool (= s38 s42))
-[GOOD] (define-fun s44 () Bool (or s41 s43))
-[GOOD] (define-fun s45 () Int (ite s36 s3 s37))
-[GOOD] (define-fun s46 () Int (+ s26 s45))
-[GOOD] (define-fun s47 () Int (ite s25 s3 s46))
-[GOOD] (define-fun s48 () Int (+ s14 s47))
-[GOOD] (define-fun s49 () Int (ite s13 s3 s48))
-[GOOD] (define-fun s50 () Int (+ s0 s1))
-[GOOD] (define-fun s51 () Int (+ s2 s50))
-[GOOD] (define-fun s52 () Bool (= s49 s51))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s11 s3 s16))
+[GOOD] (define-fun s18 () Bool (= s15 s17))
+[GOOD] (define-fun s19 () Bool (<= s12 s3))
+[GOOD] (define-fun s20 () Bool (or s18 s19))
+[GOOD] (define-fun s21 () Int (- s12 s16))
+[GOOD] (define-fun s22 () (Seq Int) (seq.extract s11 s16 s21))
+[GOOD] (define-fun s23 () Int (seq.len s22))
+[GOOD] (define-fun s24 () Bool (= s3 s23))
+[GOOD] (define-fun s26 () (Seq Int) (seq.unit s25))
+[GOOD] (define-fun s27 () (Seq Int) (seq.extract s22 s3 s16))
+[GOOD] (define-fun s28 () Bool (= s26 s27))
+[GOOD] (define-fun s29 () Bool (<= s23 s3))
+[GOOD] (define-fun s30 () Bool (or s28 s29))
+[GOOD] (define-fun s31 () Int (- s23 s16))
+[GOOD] (define-fun s32 () (Seq Int) (seq.extract s22 s16 s31))
+[GOOD] (define-fun s33 () Int (seq.len s32))
+[GOOD] (define-fun s34 () Bool (= s3 s33))
+[GOOD] (define-fun s36 () (Seq Int) (seq.unit s35))
+[GOOD] (define-fun s37 () (Seq Int) (seq.extract s32 s3 s16))
+[GOOD] (define-fun s38 () Bool (= s36 s37))
+[GOOD] (define-fun s39 () Bool (<= s33 s3))
+[GOOD] (define-fun s40 () Bool (or s38 s39))
+[GOOD] (define-fun s41 () Int (ite s34 s3 s35))
+[GOOD] (define-fun s42 () Int (+ s25 s41))
+[GOOD] (define-fun s43 () Int (ite s24 s3 s42))
+[GOOD] (define-fun s44 () Int (+ s14 s43))
+[GOOD] (define-fun s45 () Int (ite s13 s3 s44))
+[GOOD] (define-fun s46 () Int (+ s0 s1))
+[GOOD] (define-fun s47 () Int (+ s2 s46))
+[GOOD] (define-fun s48 () Bool (= s45 s47))
 [GOOD] (assert s4)
 [GOOD] (assert s5)
 [GOOD] (assert s6)
-[GOOD] (assert s22)
-[GOOD] (assert s33)
-[GOOD] (assert s44)
-[GOOD] (assert s52)
+[GOOD] (assert s20)
+[GOOD] (assert s30)
+[GOOD] (assert s40)
+[GOOD] (assert s48)
 [SEND] (check-sat)
 [RECV] sat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/foldrAB1.gold b/SBVTestSuite/GoldFiles/foldrAB1.gold
--- a/SBVTestSuite/GoldFiles/foldrAB1.gold
+++ b/SBVTestSuite/GoldFiles/foldrAB1.gold
@@ -10,10 +10,10 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () Int 0)
-[GOOD] (define-fun s15 () Int 1)
-[GOOD] (define-fun s8 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s12 () Int 1)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
@@ -29,21 +29,20 @@
 [GOOD] (define-fun s5 () (Seq Int) (seq.unit s0))
 [GOOD] (define-fun s6 () (Seq Int) (seq.unit s1))
 [GOOD] (define-fun s7 () (Seq Int) (seq.++ s5 s6))
-[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s2 s8))
 [GOOD] (define-fun s11 () (Seq Int) (seq.unit s10))
-[GOOD] (define-fun s12 () Int (seq.len s7))
-[GOOD] (define-fun s13 () Bool (> s12 s2))
-[GOOD] (define-fun s14 () Bool (not s13))
-[GOOD] (define-fun s16 () (Seq Int) (seq.extract s7 s2 s15))
-[GOOD] (define-fun s17 () Bool (= s11 s16))
-[GOOD] (define-fun s18 () Bool (or s14 s17))
-[GOOD] (define-fun s19 () Int (ite s9 s2 s10))
-[GOOD] (define-fun s20 () Int (+ s0 s1))
-[GOOD] (define-fun s21 () Bool (= s19 s20))
+[GOOD] (define-fun s13 () (Seq Int) (seq.extract s7 s2 s12))
+[GOOD] (define-fun s14 () Bool (= s11 s13))
+[GOOD] (define-fun s15 () Bool (<= s8 s2))
+[GOOD] (define-fun s16 () Bool (or s14 s15))
+[GOOD] (define-fun s17 () Int (ite s9 s2 s10))
+[GOOD] (define-fun s18 () Int (+ s0 s1))
+[GOOD] (define-fun s19 () Bool (= s17 s18))
 [GOOD] (assert s3)
 [GOOD] (assert s4)
-[GOOD] (assert s18)
-[GOOD] (assert s21)
+[GOOD] (assert s16)
+[GOOD] (assert s19)
 [SEND] (check-sat)
 [RECV] unsat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/foldrAB2.gold b/SBVTestSuite/GoldFiles/foldrAB2.gold
--- a/SBVTestSuite/GoldFiles/foldrAB2.gold
+++ b/SBVTestSuite/GoldFiles/foldrAB2.gold
@@ -10,15 +10,15 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () Int 0)
-[GOOD] (define-fun s15 () Int 1)
-[GOOD] (define-fun s8 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s12 () Int 1)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
 [GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
-[GOOD] (declare-fun s22 () Int) ; tracks user variable "__internal_sbv_s22"
+[GOOD] (declare-fun s21 () Int) ; tracks user variable "__internal_sbv_s21"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -30,34 +30,32 @@
 [GOOD] (define-fun s5 () (Seq Int) (seq.unit s0))
 [GOOD] (define-fun s6 () (Seq Int) (seq.unit s1))
 [GOOD] (define-fun s7 () (Seq Int) (seq.++ s5 s6))
-[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s2 s8))
 [GOOD] (define-fun s11 () (Seq Int) (seq.unit s10))
-[GOOD] (define-fun s12 () Int (seq.len s7))
-[GOOD] (define-fun s13 () Bool (> s12 s2))
-[GOOD] (define-fun s14 () Bool (not s13))
-[GOOD] (define-fun s16 () (Seq Int) (seq.extract s7 s2 s15))
-[GOOD] (define-fun s17 () Bool (= s11 s16))
-[GOOD] (define-fun s18 () Bool (or s14 s17))
-[GOOD] (define-fun s19 () Int (- s12 s15))
-[GOOD] (define-fun s20 () (Seq Int) (seq.extract s7 s15 s19))
-[GOOD] (define-fun s21 () Bool (= s8 s20))
-[GOOD] (define-fun s23 () (Seq Int) (seq.unit s22))
-[GOOD] (define-fun s24 () Int (seq.len s20))
-[GOOD] (define-fun s25 () Bool (> s24 s2))
-[GOOD] (define-fun s26 () Bool (not s25))
-[GOOD] (define-fun s27 () (Seq Int) (seq.extract s20 s2 s15))
-[GOOD] (define-fun s28 () Bool (= s23 s27))
-[GOOD] (define-fun s29 () Bool (or s26 s28))
-[GOOD] (define-fun s30 () Int (ite s21 s2 s22))
-[GOOD] (define-fun s31 () Int (+ s10 s30))
-[GOOD] (define-fun s32 () Int (ite s9 s2 s31))
-[GOOD] (define-fun s33 () Int (+ s0 s1))
-[GOOD] (define-fun s34 () Bool (= s32 s33))
+[GOOD] (define-fun s13 () (Seq Int) (seq.extract s7 s2 s12))
+[GOOD] (define-fun s14 () Bool (= s11 s13))
+[GOOD] (define-fun s15 () Bool (<= s8 s2))
+[GOOD] (define-fun s16 () Bool (or s14 s15))
+[GOOD] (define-fun s17 () Int (- s8 s12))
+[GOOD] (define-fun s18 () (Seq Int) (seq.extract s7 s12 s17))
+[GOOD] (define-fun s19 () Int (seq.len s18))
+[GOOD] (define-fun s20 () Bool (= s2 s19))
+[GOOD] (define-fun s22 () (Seq Int) (seq.unit s21))
+[GOOD] (define-fun s23 () (Seq Int) (seq.extract s18 s2 s12))
+[GOOD] (define-fun s24 () Bool (= s22 s23))
+[GOOD] (define-fun s25 () Bool (<= s19 s2))
+[GOOD] (define-fun s26 () Bool (or s24 s25))
+[GOOD] (define-fun s27 () Int (ite s20 s2 s21))
+[GOOD] (define-fun s28 () Int (+ s10 s27))
+[GOOD] (define-fun s29 () Int (ite s9 s2 s28))
+[GOOD] (define-fun s30 () Int (+ s0 s1))
+[GOOD] (define-fun s31 () Bool (= s29 s30))
 [GOOD] (assert s3)
 [GOOD] (assert s4)
-[GOOD] (assert s18)
-[GOOD] (assert s29)
-[GOOD] (assert s34)
+[GOOD] (assert s16)
+[GOOD] (assert s26)
+[GOOD] (assert s31)
 [SEND] (check-sat)
 [RECV] sat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/foldrAB3.gold b/SBVTestSuite/GoldFiles/foldrAB3.gold
--- a/SBVTestSuite/GoldFiles/foldrAB3.gold
+++ b/SBVTestSuite/GoldFiles/foldrAB3.gold
@@ -10,16 +10,16 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () Int 0)
-[GOOD] (define-fun s15 () Int 1)
-[GOOD] (define-fun s8 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s12 () Int 1)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
 [GOOD] (declare-fun s10 () Int) ; tracks user variable "__internal_sbv_s10"
-[GOOD] (declare-fun s22 () Int) ; tracks user variable "__internal_sbv_s22"
-[GOOD] (declare-fun s33 () Int) ; tracks user variable "__internal_sbv_s33"
+[GOOD] (declare-fun s21 () Int) ; tracks user variable "__internal_sbv_s21"
+[GOOD] (declare-fun s31 () Int) ; tracks user variable "__internal_sbv_s31"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -31,47 +31,44 @@
 [GOOD] (define-fun s5 () (Seq Int) (seq.unit s0))
 [GOOD] (define-fun s6 () (Seq Int) (seq.unit s1))
 [GOOD] (define-fun s7 () (Seq Int) (seq.++ s5 s6))
-[GOOD] (define-fun s9 () Bool (= s7 s8))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s2 s8))
 [GOOD] (define-fun s11 () (Seq Int) (seq.unit s10))
-[GOOD] (define-fun s12 () Int (seq.len s7))
-[GOOD] (define-fun s13 () Bool (> s12 s2))
-[GOOD] (define-fun s14 () Bool (not s13))
-[GOOD] (define-fun s16 () (Seq Int) (seq.extract s7 s2 s15))
-[GOOD] (define-fun s17 () Bool (= s11 s16))
-[GOOD] (define-fun s18 () Bool (or s14 s17))
-[GOOD] (define-fun s19 () Int (- s12 s15))
-[GOOD] (define-fun s20 () (Seq Int) (seq.extract s7 s15 s19))
-[GOOD] (define-fun s21 () Bool (= s8 s20))
-[GOOD] (define-fun s23 () (Seq Int) (seq.unit s22))
-[GOOD] (define-fun s24 () Int (seq.len s20))
-[GOOD] (define-fun s25 () Bool (> s24 s2))
-[GOOD] (define-fun s26 () Bool (not s25))
-[GOOD] (define-fun s27 () (Seq Int) (seq.extract s20 s2 s15))
-[GOOD] (define-fun s28 () Bool (= s23 s27))
-[GOOD] (define-fun s29 () Bool (or s26 s28))
-[GOOD] (define-fun s30 () Int (- s24 s15))
-[GOOD] (define-fun s31 () (Seq Int) (seq.extract s20 s15 s30))
-[GOOD] (define-fun s32 () Bool (= s8 s31))
-[GOOD] (define-fun s34 () (Seq Int) (seq.unit s33))
-[GOOD] (define-fun s35 () Int (seq.len s31))
-[GOOD] (define-fun s36 () Bool (> s35 s2))
-[GOOD] (define-fun s37 () Bool (not s36))
-[GOOD] (define-fun s38 () (Seq Int) (seq.extract s31 s2 s15))
-[GOOD] (define-fun s39 () Bool (= s34 s38))
-[GOOD] (define-fun s40 () Bool (or s37 s39))
-[GOOD] (define-fun s41 () Int (ite s32 s2 s33))
-[GOOD] (define-fun s42 () Int (+ s22 s41))
-[GOOD] (define-fun s43 () Int (ite s21 s2 s42))
-[GOOD] (define-fun s44 () Int (+ s10 s43))
-[GOOD] (define-fun s45 () Int (ite s9 s2 s44))
-[GOOD] (define-fun s46 () Int (+ s0 s1))
-[GOOD] (define-fun s47 () Bool (= s45 s46))
+[GOOD] (define-fun s13 () (Seq Int) (seq.extract s7 s2 s12))
+[GOOD] (define-fun s14 () Bool (= s11 s13))
+[GOOD] (define-fun s15 () Bool (<= s8 s2))
+[GOOD] (define-fun s16 () Bool (or s14 s15))
+[GOOD] (define-fun s17 () Int (- s8 s12))
+[GOOD] (define-fun s18 () (Seq Int) (seq.extract s7 s12 s17))
+[GOOD] (define-fun s19 () Int (seq.len s18))
+[GOOD] (define-fun s20 () Bool (= s2 s19))
+[GOOD] (define-fun s22 () (Seq Int) (seq.unit s21))
+[GOOD] (define-fun s23 () (Seq Int) (seq.extract s18 s2 s12))
+[GOOD] (define-fun s24 () Bool (= s22 s23))
+[GOOD] (define-fun s25 () Bool (<= s19 s2))
+[GOOD] (define-fun s26 () Bool (or s24 s25))
+[GOOD] (define-fun s27 () Int (- s19 s12))
+[GOOD] (define-fun s28 () (Seq Int) (seq.extract s18 s12 s27))
+[GOOD] (define-fun s29 () Int (seq.len s28))
+[GOOD] (define-fun s30 () Bool (= s2 s29))
+[GOOD] (define-fun s32 () (Seq Int) (seq.unit s31))
+[GOOD] (define-fun s33 () (Seq Int) (seq.extract s28 s2 s12))
+[GOOD] (define-fun s34 () Bool (= s32 s33))
+[GOOD] (define-fun s35 () Bool (<= s29 s2))
+[GOOD] (define-fun s36 () Bool (or s34 s35))
+[GOOD] (define-fun s37 () Int (ite s30 s2 s31))
+[GOOD] (define-fun s38 () Int (+ s21 s37))
+[GOOD] (define-fun s39 () Int (ite s20 s2 s38))
+[GOOD] (define-fun s40 () Int (+ s10 s39))
+[GOOD] (define-fun s41 () Int (ite s9 s2 s40))
+[GOOD] (define-fun s42 () Int (+ s0 s1))
+[GOOD] (define-fun s43 () Bool (= s41 s42))
 [GOOD] (assert s3)
 [GOOD] (assert s4)
-[GOOD] (assert s18)
-[GOOD] (assert s29)
-[GOOD] (assert s40)
-[GOOD] (assert s47)
+[GOOD] (assert s16)
+[GOOD] (assert s26)
+[GOOD] (assert s36)
+[GOOD] (assert s43)
 [SEND] (check-sat)
 [RECV] sat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/freshVars.gold b/SBVTestSuite/GoldFiles/freshVars.gold
--- a/SBVTestSuite/GoldFiles/freshVars.gold
+++ b/SBVTestSuite/GoldFiles/freshVars.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () Int 0)
 [GOOD] ; --- skolem constants ---
@@ -35,7 +36,7 @@
 [GOOD] (declare-fun s13 () (_ FloatingPoint 11 53))
 [GOOD] (declare-fun s14 () Real)
 [GOOD] (declare-fun s15 () Int)
-[GOOD] (declare-datatypes () ((BinOp (Plus) (Minus) (Times))))
+[GOOD] (declare-datatypes ((BinOp 0)) (((Plus) (Minus) (Times))))
 [GOOD] (define-fun BinOp_constrIndex ((x BinOp)) Int
           (ite (= x Plus) 0 (ite (= x Minus) 1 2))
        )
@@ -109,9 +110,17 @@
 [GOOD] (define-fun s61 () Bool (not s44))
 [GOOD] (assert s61)
 [GOOD] (declare-fun s62 () String)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (declare-fun s63 () (Seq Int))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (declare-fun s64 () (Seq (Seq Int)))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (declare-fun s65 () (Seq (_ BitVec 8)))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (declare-fun s66 () (Seq (Seq (_ BitVec 16))))
 [GOOD] (define-fun s67 () String "hello")
 [GOOD] (define-fun s68 () Bool (= s62 s67))
diff --git a/SBVTestSuite/GoldFiles/genBenchMark1.gold b/SBVTestSuite/GoldFiles/genBenchMark1.gold
--- a/SBVTestSuite/GoldFiles/genBenchMark1.gold
+++ b/SBVTestSuite/GoldFiles/genBenchMark1.gold
@@ -4,6 +4,7 @@
 (set-logic QF_BV)
 ; --- uninterpreted sorts ---
 ; --- tuples ---
+; --- sums ---
 ; --- literal constants ---
 (define-fun s1 () (_ BitVec 8) #x01)
 ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/genBenchMark2.gold b/SBVTestSuite/GoldFiles/genBenchMark2.gold
--- a/SBVTestSuite/GoldFiles/genBenchMark2.gold
+++ b/SBVTestSuite/GoldFiles/genBenchMark2.gold
@@ -4,6 +4,7 @@
 (set-logic QF_BV)
 ; --- uninterpreted sorts ---
 ; --- tuples ---
+; --- sums ---
 ; --- literal constants ---
 (define-fun s1 () (_ BitVec 8) #x01)
 ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/listSum.gold b/SBVTestSuite/GoldFiles/listSum.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/listSum.gold
@@ -0,0 +1,60 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVSum2 2)) (
+         (par (X Y) ( (left (getLeft X)) (right (getRight Y)) ))
+       ))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s9 () Int 1)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Seq (SBVSum2 Int (_ BitVec 8)))) ; tracks user variable "x"
+[GOOD] (declare-fun s4 () (SBVSum2 Int (_ BitVec 8))) ; tracks user variable "__internal_sbv_s4"
+[GOOD] (declare-fun s15 () (SBVSum2 Int (_ BitVec 8))) ; tracks user variable "__internal_sbv_s15"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int (seq.len s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () (Seq (SBVSum2 Int (_ BitVec 8))) (seq.unit s4))
+[GOOD] (define-fun s7 () Bool (> s1 s6))
+[GOOD] (define-fun s8 () Bool (not s7))
+[GOOD] (define-fun s10 () (Seq (SBVSum2 Int (_ BitVec 8))) (seq.extract s0 s6 s9))
+[GOOD] (define-fun s11 () Bool (= s5 s10))
+[GOOD] (define-fun s12 () Bool (or s8 s11))
+[GOOD] (define-fun s13 () Bool ((_ is left) s4))
+[GOOD] (define-fun s14 () Bool (ite s13 true false))
+[GOOD] (define-fun s16 () (Seq (SBVSum2 Int (_ BitVec 8))) (seq.unit s15))
+[GOOD] (define-fun s17 () Int (- s1 s9))
+[GOOD] (define-fun s18 () (Seq (SBVSum2 Int (_ BitVec 8))) (seq.extract s0 s9 s17))
+[GOOD] (define-fun s19 () Int (seq.len s18))
+[GOOD] (define-fun s20 () Bool (> s19 s6))
+[GOOD] (define-fun s21 () Bool (not s20))
+[GOOD] (define-fun s22 () (Seq (SBVSum2 Int (_ BitVec 8))) (seq.extract s18 s6 s9))
+[GOOD] (define-fun s23 () Bool (= s16 s22))
+[GOOD] (define-fun s24 () Bool (or s21 s23))
+[GOOD] (define-fun s25 () Bool ((_ is left) s15))
+[GOOD] (define-fun s26 () Bool (ite s25 false true))
+[GOOD] (assert s3)
+[GOOD] (assert s12)
+[GOOD] (assert s14)
+[GOOD] (assert s24)
+[GOOD] (assert s26)
+[SEND] (check-sat)
+[RECV] sat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/makePair.gold b/SBVTestSuite/GoldFiles/makePair.gold
--- a/SBVTestSuite/GoldFiles/makePair.gold
+++ b/SBVTestSuite/GoldFiles/makePair.gold
@@ -9,6 +9,7 @@
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes (T1 T2) ((tup-2 (mk-tup-2 (proj-1 T1) (proj-2 T2)))))
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s_2 () Bool false)
 [GOOD] (define-fun s_1 () Bool true)
diff --git a/SBVTestSuite/GoldFiles/mapNoFailure.gold b/SBVTestSuite/GoldFiles/mapNoFailure.gold
--- a/SBVTestSuite/GoldFiles/mapNoFailure.gold
+++ b/SBVTestSuite/GoldFiles/mapNoFailure.gold
@@ -10,26 +10,26 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s5 () Int 6)
 [GOOD] (define-fun s7 () Int 0)
 [GOOD] (define-fun s20 () Int 1)
-[GOOD] (define-fun s66 () Int 10)
-[GOOD] (define-fun s18 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s64 () Int 10)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
 [GOOD] (declare-fun s2 () Int) ; tracks user variable "c"
 [GOOD] (declare-fun s57 () Int) ; tracks user variable "__internal_sbv_s57"
-[GOOD] (declare-fun s71 () Int) ; tracks user variable "__internal_sbv_s71"
-[GOOD] (declare-fun s84 () Int) ; tracks user variable "__internal_sbv_s84"
-[GOOD] (declare-fun s97 () Int) ; tracks user variable "__internal_sbv_s97"
-[GOOD] (declare-fun s110 () Int) ; tracks user variable "__internal_sbv_s110"
-[GOOD] (declare-fun s123 () Int) ; tracks user variable "__internal_sbv_s123"
-[GOOD] (declare-fun s136 () Int) ; tracks user variable "__internal_sbv_s136"
-[GOOD] (declare-fun s149 () Int) ; tracks user variable "__internal_sbv_s149"
-[GOOD] (declare-fun s162 () Int) ; tracks user variable "__internal_sbv_s162"
-[GOOD] (declare-fun s175 () Int) ; tracks user variable "__internal_sbv_s175"
+[GOOD] (declare-fun s69 () Int) ; tracks user variable "__internal_sbv_s69"
+[GOOD] (declare-fun s81 () Int) ; tracks user variable "__internal_sbv_s81"
+[GOOD] (declare-fun s93 () Int) ; tracks user variable "__internal_sbv_s93"
+[GOOD] (declare-fun s105 () Int) ; tracks user variable "__internal_sbv_s105"
+[GOOD] (declare-fun s117 () Int) ; tracks user variable "__internal_sbv_s117"
+[GOOD] (declare-fun s129 () Int) ; tracks user variable "__internal_sbv_s129"
+[GOOD] (declare-fun s141 () Int) ; tracks user variable "__internal_sbv_s141"
+[GOOD] (declare-fun s153 () Int) ; tracks user variable "__internal_sbv_s153"
+[GOOD] (declare-fun s165 () Int) ; tracks user variable "__internal_sbv_s165"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -49,176 +49,166 @@
 [GOOD] (define-fun s15 () (Seq Int) (seq.unit s2))
 [GOOD] (define-fun s16 () (Seq Int) (seq.++ s14 s15))
 [GOOD] (define-fun s17 () (Seq Int) (seq.++ s13 s16))
-[GOOD] (define-fun s19 () Bool (= s17 s18))
-[GOOD] (define-fun s21 () Int (seq.len s17))
-[GOOD] (define-fun s22 () Int (- s21 s20))
-[GOOD] (define-fun s23 () (Seq Int) (seq.extract s17 s20 s22))
-[GOOD] (define-fun s24 () Bool (= s18 s23))
-[GOOD] (define-fun s25 () Int (seq.len s23))
-[GOOD] (define-fun s26 () Int (- s25 s20))
-[GOOD] (define-fun s27 () (Seq Int) (seq.extract s23 s20 s26))
-[GOOD] (define-fun s28 () Bool (= s18 s27))
-[GOOD] (define-fun s29 () Int (seq.len s27))
-[GOOD] (define-fun s30 () Int (- s29 s20))
-[GOOD] (define-fun s31 () (Seq Int) (seq.extract s27 s20 s30))
-[GOOD] (define-fun s32 () Bool (= s18 s31))
-[GOOD] (define-fun s33 () Int (seq.len s31))
-[GOOD] (define-fun s34 () Int (- s33 s20))
-[GOOD] (define-fun s35 () (Seq Int) (seq.extract s31 s20 s34))
-[GOOD] (define-fun s36 () Bool (= s18 s35))
-[GOOD] (define-fun s37 () Int (seq.len s35))
-[GOOD] (define-fun s38 () Int (- s37 s20))
-[GOOD] (define-fun s39 () (Seq Int) (seq.extract s35 s20 s38))
-[GOOD] (define-fun s40 () Bool (= s18 s39))
-[GOOD] (define-fun s41 () Int (seq.len s39))
-[GOOD] (define-fun s42 () Int (- s41 s20))
-[GOOD] (define-fun s43 () (Seq Int) (seq.extract s39 s20 s42))
-[GOOD] (define-fun s44 () Bool (= s18 s43))
-[GOOD] (define-fun s45 () Int (seq.len s43))
-[GOOD] (define-fun s46 () Int (- s45 s20))
-[GOOD] (define-fun s47 () (Seq Int) (seq.extract s43 s20 s46))
-[GOOD] (define-fun s48 () Bool (= s18 s47))
-[GOOD] (define-fun s49 () Int (seq.len s47))
-[GOOD] (define-fun s50 () Int (- s49 s20))
-[GOOD] (define-fun s51 () (Seq Int) (seq.extract s47 s20 s50))
-[GOOD] (define-fun s52 () Bool (= s18 s51))
-[GOOD] (define-fun s53 () Int (seq.len s51))
-[GOOD] (define-fun s54 () Int (- s53 s20))
-[GOOD] (define-fun s55 () (Seq Int) (seq.extract s51 s20 s54))
-[GOOD] (define-fun s56 () Bool (= s18 s55))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (= s7 s18))
+[GOOD] (define-fun s21 () Int (- s18 s20))
+[GOOD] (define-fun s22 () (Seq Int) (seq.extract s17 s20 s21))
+[GOOD] (define-fun s23 () Int (seq.len s22))
+[GOOD] (define-fun s24 () Bool (= s7 s23))
+[GOOD] (define-fun s25 () Int (- s23 s20))
+[GOOD] (define-fun s26 () (Seq Int) (seq.extract s22 s20 s25))
+[GOOD] (define-fun s27 () Int (seq.len s26))
+[GOOD] (define-fun s28 () Bool (= s7 s27))
+[GOOD] (define-fun s29 () Int (- s27 s20))
+[GOOD] (define-fun s30 () (Seq Int) (seq.extract s26 s20 s29))
+[GOOD] (define-fun s31 () Int (seq.len s30))
+[GOOD] (define-fun s32 () Bool (= s7 s31))
+[GOOD] (define-fun s33 () Int (- s31 s20))
+[GOOD] (define-fun s34 () (Seq Int) (seq.extract s30 s20 s33))
+[GOOD] (define-fun s35 () Int (seq.len s34))
+[GOOD] (define-fun s36 () Bool (= s7 s35))
+[GOOD] (define-fun s37 () Int (- s35 s20))
+[GOOD] (define-fun s38 () (Seq Int) (seq.extract s34 s20 s37))
+[GOOD] (define-fun s39 () Int (seq.len s38))
+[GOOD] (define-fun s40 () Bool (= s7 s39))
+[GOOD] (define-fun s41 () Int (- s39 s20))
+[GOOD] (define-fun s42 () (Seq Int) (seq.extract s38 s20 s41))
+[GOOD] (define-fun s43 () Int (seq.len s42))
+[GOOD] (define-fun s44 () Bool (= s7 s43))
+[GOOD] (define-fun s45 () Int (- s43 s20))
+[GOOD] (define-fun s46 () (Seq Int) (seq.extract s42 s20 s45))
+[GOOD] (define-fun s47 () Int (seq.len s46))
+[GOOD] (define-fun s48 () Bool (= s7 s47))
+[GOOD] (define-fun s49 () Int (- s47 s20))
+[GOOD] (define-fun s50 () (Seq Int) (seq.extract s46 s20 s49))
+[GOOD] (define-fun s51 () Int (seq.len s50))
+[GOOD] (define-fun s52 () Bool (= s7 s51))
+[GOOD] (define-fun s53 () Int (- s51 s20))
+[GOOD] (define-fun s54 () (Seq Int) (seq.extract s50 s20 s53))
+[GOOD] (define-fun s55 () Int (seq.len s54))
+[GOOD] (define-fun s56 () Bool (= s7 s55))
 [GOOD] (define-fun s58 () (Seq Int) (seq.unit s57))
-[GOOD] (define-fun s59 () Int (seq.len s55))
-[GOOD] (define-fun s60 () Bool (> s59 s7))
-[GOOD] (define-fun s61 () Bool (not s60))
-[GOOD] (define-fun s62 () (Seq Int) (seq.extract s55 s7 s20))
-[GOOD] (define-fun s63 () Bool (= s58 s62))
-[GOOD] (define-fun s64 () Bool (or s61 s63))
-[GOOD] (define-fun s65 () Bool (< s57 s7))
-[GOOD] (define-fun s67 () Bool (> s57 s66))
-[GOOD] (define-fun s68 () Bool (or s65 s67))
-[GOOD] (define-fun s69 () Bool (not s56))
-[GOOD] (define-fun s70 () Bool (and s68 s69))
-[GOOD] (define-fun s72 () (Seq Int) (seq.unit s71))
-[GOOD] (define-fun s73 () Bool (> s53 s7))
-[GOOD] (define-fun s74 () Bool (not s73))
-[GOOD] (define-fun s75 () (Seq Int) (seq.extract s51 s7 s20))
-[GOOD] (define-fun s76 () Bool (= s72 s75))
-[GOOD] (define-fun s77 () Bool (or s74 s76))
-[GOOD] (define-fun s78 () Bool (< s71 s7))
-[GOOD] (define-fun s79 () Bool (> s71 s66))
-[GOOD] (define-fun s80 () Bool (or s78 s79))
-[GOOD] (define-fun s81 () Bool (or s70 s80))
-[GOOD] (define-fun s82 () Bool (not s52))
-[GOOD] (define-fun s83 () Bool (and s81 s82))
-[GOOD] (define-fun s85 () (Seq Int) (seq.unit s84))
-[GOOD] (define-fun s86 () Bool (> s49 s7))
-[GOOD] (define-fun s87 () Bool (not s86))
-[GOOD] (define-fun s88 () (Seq Int) (seq.extract s47 s7 s20))
-[GOOD] (define-fun s89 () Bool (= s85 s88))
-[GOOD] (define-fun s90 () Bool (or s87 s89))
-[GOOD] (define-fun s91 () Bool (< s84 s7))
-[GOOD] (define-fun s92 () Bool (> s84 s66))
-[GOOD] (define-fun s93 () Bool (or s91 s92))
-[GOOD] (define-fun s94 () Bool (or s83 s93))
-[GOOD] (define-fun s95 () Bool (not s48))
-[GOOD] (define-fun s96 () Bool (and s94 s95))
-[GOOD] (define-fun s98 () (Seq Int) (seq.unit s97))
-[GOOD] (define-fun s99 () Bool (> s45 s7))
-[GOOD] (define-fun s100 () Bool (not s99))
-[GOOD] (define-fun s101 () (Seq Int) (seq.extract s43 s7 s20))
-[GOOD] (define-fun s102 () Bool (= s98 s101))
-[GOOD] (define-fun s103 () Bool (or s100 s102))
-[GOOD] (define-fun s104 () Bool (< s97 s7))
-[GOOD] (define-fun s105 () Bool (> s97 s66))
-[GOOD] (define-fun s106 () Bool (or s104 s105))
-[GOOD] (define-fun s107 () Bool (or s96 s106))
-[GOOD] (define-fun s108 () Bool (not s44))
-[GOOD] (define-fun s109 () Bool (and s107 s108))
-[GOOD] (define-fun s111 () (Seq Int) (seq.unit s110))
-[GOOD] (define-fun s112 () Bool (> s41 s7))
-[GOOD] (define-fun s113 () Bool (not s112))
-[GOOD] (define-fun s114 () (Seq Int) (seq.extract s39 s7 s20))
-[GOOD] (define-fun s115 () Bool (= s111 s114))
-[GOOD] (define-fun s116 () Bool (or s113 s115))
-[GOOD] (define-fun s117 () Bool (< s110 s7))
-[GOOD] (define-fun s118 () Bool (> s110 s66))
-[GOOD] (define-fun s119 () Bool (or s117 s118))
-[GOOD] (define-fun s120 () Bool (or s109 s119))
-[GOOD] (define-fun s121 () Bool (not s40))
-[GOOD] (define-fun s122 () Bool (and s120 s121))
-[GOOD] (define-fun s124 () (Seq Int) (seq.unit s123))
-[GOOD] (define-fun s125 () Bool (> s37 s7))
-[GOOD] (define-fun s126 () Bool (not s125))
-[GOOD] (define-fun s127 () (Seq Int) (seq.extract s35 s7 s20))
-[GOOD] (define-fun s128 () Bool (= s124 s127))
-[GOOD] (define-fun s129 () Bool (or s126 s128))
-[GOOD] (define-fun s130 () Bool (< s123 s7))
-[GOOD] (define-fun s131 () Bool (> s123 s66))
-[GOOD] (define-fun s132 () Bool (or s130 s131))
-[GOOD] (define-fun s133 () Bool (or s122 s132))
-[GOOD] (define-fun s134 () Bool (not s36))
-[GOOD] (define-fun s135 () Bool (and s133 s134))
-[GOOD] (define-fun s137 () (Seq Int) (seq.unit s136))
-[GOOD] (define-fun s138 () Bool (> s33 s7))
-[GOOD] (define-fun s139 () Bool (not s138))
-[GOOD] (define-fun s140 () (Seq Int) (seq.extract s31 s7 s20))
-[GOOD] (define-fun s141 () Bool (= s137 s140))
-[GOOD] (define-fun s142 () Bool (or s139 s141))
-[GOOD] (define-fun s143 () Bool (< s136 s7))
-[GOOD] (define-fun s144 () Bool (> s136 s66))
-[GOOD] (define-fun s145 () Bool (or s143 s144))
-[GOOD] (define-fun s146 () Bool (or s135 s145))
-[GOOD] (define-fun s147 () Bool (not s32))
-[GOOD] (define-fun s148 () Bool (and s146 s147))
-[GOOD] (define-fun s150 () (Seq Int) (seq.unit s149))
-[GOOD] (define-fun s151 () Bool (> s29 s7))
-[GOOD] (define-fun s152 () Bool (not s151))
-[GOOD] (define-fun s153 () (Seq Int) (seq.extract s27 s7 s20))
-[GOOD] (define-fun s154 () Bool (= s150 s153))
-[GOOD] (define-fun s155 () Bool (or s152 s154))
-[GOOD] (define-fun s156 () Bool (< s149 s7))
-[GOOD] (define-fun s157 () Bool (> s149 s66))
+[GOOD] (define-fun s59 () (Seq Int) (seq.extract s54 s7 s20))
+[GOOD] (define-fun s60 () Bool (= s58 s59))
+[GOOD] (define-fun s61 () Bool (<= s55 s7))
+[GOOD] (define-fun s62 () Bool (or s60 s61))
+[GOOD] (define-fun s63 () Bool (< s57 s7))
+[GOOD] (define-fun s65 () Bool (> s57 s64))
+[GOOD] (define-fun s66 () Bool (or s63 s65))
+[GOOD] (define-fun s67 () Bool (not s56))
+[GOOD] (define-fun s68 () Bool (and s66 s67))
+[GOOD] (define-fun s70 () (Seq Int) (seq.unit s69))
+[GOOD] (define-fun s71 () (Seq Int) (seq.extract s50 s7 s20))
+[GOOD] (define-fun s72 () Bool (= s70 s71))
+[GOOD] (define-fun s73 () Bool (<= s51 s7))
+[GOOD] (define-fun s74 () Bool (or s72 s73))
+[GOOD] (define-fun s75 () Bool (< s69 s7))
+[GOOD] (define-fun s76 () Bool (> s69 s64))
+[GOOD] (define-fun s77 () Bool (or s75 s76))
+[GOOD] (define-fun s78 () Bool (or s68 s77))
+[GOOD] (define-fun s79 () Bool (not s52))
+[GOOD] (define-fun s80 () Bool (and s78 s79))
+[GOOD] (define-fun s82 () (Seq Int) (seq.unit s81))
+[GOOD] (define-fun s83 () (Seq Int) (seq.extract s46 s7 s20))
+[GOOD] (define-fun s84 () Bool (= s82 s83))
+[GOOD] (define-fun s85 () Bool (<= s47 s7))
+[GOOD] (define-fun s86 () Bool (or s84 s85))
+[GOOD] (define-fun s87 () Bool (< s81 s7))
+[GOOD] (define-fun s88 () Bool (> s81 s64))
+[GOOD] (define-fun s89 () Bool (or s87 s88))
+[GOOD] (define-fun s90 () Bool (or s80 s89))
+[GOOD] (define-fun s91 () Bool (not s48))
+[GOOD] (define-fun s92 () Bool (and s90 s91))
+[GOOD] (define-fun s94 () (Seq Int) (seq.unit s93))
+[GOOD] (define-fun s95 () (Seq Int) (seq.extract s42 s7 s20))
+[GOOD] (define-fun s96 () Bool (= s94 s95))
+[GOOD] (define-fun s97 () Bool (<= s43 s7))
+[GOOD] (define-fun s98 () Bool (or s96 s97))
+[GOOD] (define-fun s99 () Bool (< s93 s7))
+[GOOD] (define-fun s100 () Bool (> s93 s64))
+[GOOD] (define-fun s101 () Bool (or s99 s100))
+[GOOD] (define-fun s102 () Bool (or s92 s101))
+[GOOD] (define-fun s103 () Bool (not s44))
+[GOOD] (define-fun s104 () Bool (and s102 s103))
+[GOOD] (define-fun s106 () (Seq Int) (seq.unit s105))
+[GOOD] (define-fun s107 () (Seq Int) (seq.extract s38 s7 s20))
+[GOOD] (define-fun s108 () Bool (= s106 s107))
+[GOOD] (define-fun s109 () Bool (<= s39 s7))
+[GOOD] (define-fun s110 () Bool (or s108 s109))
+[GOOD] (define-fun s111 () Bool (< s105 s7))
+[GOOD] (define-fun s112 () Bool (> s105 s64))
+[GOOD] (define-fun s113 () Bool (or s111 s112))
+[GOOD] (define-fun s114 () Bool (or s104 s113))
+[GOOD] (define-fun s115 () Bool (not s40))
+[GOOD] (define-fun s116 () Bool (and s114 s115))
+[GOOD] (define-fun s118 () (Seq Int) (seq.unit s117))
+[GOOD] (define-fun s119 () (Seq Int) (seq.extract s34 s7 s20))
+[GOOD] (define-fun s120 () Bool (= s118 s119))
+[GOOD] (define-fun s121 () Bool (<= s35 s7))
+[GOOD] (define-fun s122 () Bool (or s120 s121))
+[GOOD] (define-fun s123 () Bool (< s117 s7))
+[GOOD] (define-fun s124 () Bool (> s117 s64))
+[GOOD] (define-fun s125 () Bool (or s123 s124))
+[GOOD] (define-fun s126 () Bool (or s116 s125))
+[GOOD] (define-fun s127 () Bool (not s36))
+[GOOD] (define-fun s128 () Bool (and s126 s127))
+[GOOD] (define-fun s130 () (Seq Int) (seq.unit s129))
+[GOOD] (define-fun s131 () (Seq Int) (seq.extract s30 s7 s20))
+[GOOD] (define-fun s132 () Bool (= s130 s131))
+[GOOD] (define-fun s133 () Bool (<= s31 s7))
+[GOOD] (define-fun s134 () Bool (or s132 s133))
+[GOOD] (define-fun s135 () Bool (< s129 s7))
+[GOOD] (define-fun s136 () Bool (> s129 s64))
+[GOOD] (define-fun s137 () Bool (or s135 s136))
+[GOOD] (define-fun s138 () Bool (or s128 s137))
+[GOOD] (define-fun s139 () Bool (not s32))
+[GOOD] (define-fun s140 () Bool (and s138 s139))
+[GOOD] (define-fun s142 () (Seq Int) (seq.unit s141))
+[GOOD] (define-fun s143 () (Seq Int) (seq.extract s26 s7 s20))
+[GOOD] (define-fun s144 () Bool (= s142 s143))
+[GOOD] (define-fun s145 () Bool (<= s27 s7))
+[GOOD] (define-fun s146 () Bool (or s144 s145))
+[GOOD] (define-fun s147 () Bool (< s141 s7))
+[GOOD] (define-fun s148 () Bool (> s141 s64))
+[GOOD] (define-fun s149 () Bool (or s147 s148))
+[GOOD] (define-fun s150 () Bool (or s140 s149))
+[GOOD] (define-fun s151 () Bool (not s28))
+[GOOD] (define-fun s152 () Bool (and s150 s151))
+[GOOD] (define-fun s154 () (Seq Int) (seq.unit s153))
+[GOOD] (define-fun s155 () (Seq Int) (seq.extract s22 s7 s20))
+[GOOD] (define-fun s156 () Bool (= s154 s155))
+[GOOD] (define-fun s157 () Bool (<= s23 s7))
 [GOOD] (define-fun s158 () Bool (or s156 s157))
-[GOOD] (define-fun s159 () Bool (or s148 s158))
-[GOOD] (define-fun s160 () Bool (not s28))
-[GOOD] (define-fun s161 () Bool (and s159 s160))
-[GOOD] (define-fun s163 () (Seq Int) (seq.unit s162))
-[GOOD] (define-fun s164 () Bool (> s25 s7))
-[GOOD] (define-fun s165 () Bool (not s164))
-[GOOD] (define-fun s166 () (Seq Int) (seq.extract s23 s7 s20))
-[GOOD] (define-fun s167 () Bool (= s163 s166))
-[GOOD] (define-fun s168 () Bool (or s165 s167))
-[GOOD] (define-fun s169 () Bool (< s162 s7))
-[GOOD] (define-fun s170 () Bool (> s162 s66))
-[GOOD] (define-fun s171 () Bool (or s169 s170))
-[GOOD] (define-fun s172 () Bool (or s161 s171))
-[GOOD] (define-fun s173 () Bool (not s24))
-[GOOD] (define-fun s174 () Bool (and s172 s173))
-[GOOD] (define-fun s176 () (Seq Int) (seq.unit s175))
-[GOOD] (define-fun s177 () Bool (> s21 s7))
-[GOOD] (define-fun s178 () Bool (not s177))
-[GOOD] (define-fun s179 () (Seq Int) (seq.extract s17 s7 s20))
-[GOOD] (define-fun s180 () Bool (= s176 s179))
-[GOOD] (define-fun s181 () Bool (or s178 s180))
-[GOOD] (define-fun s182 () Bool (< s175 s7))
-[GOOD] (define-fun s183 () Bool (> s175 s66))
-[GOOD] (define-fun s184 () Bool (or s182 s183))
-[GOOD] (define-fun s185 () Bool (or s174 s184))
-[GOOD] (define-fun s186 () Bool (not s19))
-[GOOD] (define-fun s187 () Bool (and s185 s186))
+[GOOD] (define-fun s159 () Bool (< s153 s7))
+[GOOD] (define-fun s160 () Bool (> s153 s64))
+[GOOD] (define-fun s161 () Bool (or s159 s160))
+[GOOD] (define-fun s162 () Bool (or s152 s161))
+[GOOD] (define-fun s163 () Bool (not s24))
+[GOOD] (define-fun s164 () Bool (and s162 s163))
+[GOOD] (define-fun s166 () (Seq Int) (seq.unit s165))
+[GOOD] (define-fun s167 () (Seq Int) (seq.extract s17 s7 s20))
+[GOOD] (define-fun s168 () Bool (= s166 s167))
+[GOOD] (define-fun s169 () Bool (<= s18 s7))
+[GOOD] (define-fun s170 () Bool (or s168 s169))
+[GOOD] (define-fun s171 () Bool (< s165 s7))
+[GOOD] (define-fun s172 () Bool (> s165 s64))
+[GOOD] (define-fun s173 () Bool (or s171 s172))
+[GOOD] (define-fun s174 () Bool (or s164 s173))
+[GOOD] (define-fun s175 () Bool (not s19))
+[GOOD] (define-fun s176 () Bool (and s174 s175))
 [GOOD] (assert s6)
 [GOOD] (assert s12)
-[GOOD] (assert s64)
-[GOOD] (assert s77)
-[GOOD] (assert s90)
-[GOOD] (assert s103)
-[GOOD] (assert s116)
-[GOOD] (assert s129)
-[GOOD] (assert s142)
-[GOOD] (assert s155)
-[GOOD] (assert s168)
-[GOOD] (assert s181)
-[GOOD] (assert s187)
+[GOOD] (assert s62)
+[GOOD] (assert s74)
+[GOOD] (assert s86)
+[GOOD] (assert s98)
+[GOOD] (assert s110)
+[GOOD] (assert s122)
+[GOOD] (assert s134)
+[GOOD] (assert s146)
+[GOOD] (assert s158)
+[GOOD] (assert s170)
+[GOOD] (assert s176)
 [SEND] (check-sat)
 [RECV] unsat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/mapWithFailure.gold b/SBVTestSuite/GoldFiles/mapWithFailure.gold
--- a/SBVTestSuite/GoldFiles/mapWithFailure.gold
+++ b/SBVTestSuite/GoldFiles/mapWithFailure.gold
@@ -10,26 +10,27 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s8 () Int 0)
-[GOOD] (define-fun s11 () Int 1)
-[GOOD] (define-fun s154 () Int 2)
-[GOOD] (define-fun s160 () Int 11)
-[GOOD] (define-fun s164 () Int 10)
-[GOOD] (define-fun s3 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s4 () Int 0)
+[GOOD] (define-fun s9 () Int 1)
+[GOOD] (define-fun s143 () Int 2)
+[GOOD] (define-fun s149 () Int 11)
+[GOOD] (define-fun s153 () Int 10)
+[GOOD] (define-fun s6 () (Seq Int) (as seq.empty (Seq Int)))
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "ints"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "__internal_sbv_s1"
-[GOOD] (declare-fun s5 () Int) ; tracks user variable "__internal_sbv_s5"
+[GOOD] (declare-fun s7 () Int) ; tracks user variable "__internal_sbv_s7"
 [GOOD] (declare-fun s20 () Int) ; tracks user variable "__internal_sbv_s20"
-[GOOD] (declare-fun s33 () Int) ; tracks user variable "__internal_sbv_s33"
-[GOOD] (declare-fun s46 () Int) ; tracks user variable "__internal_sbv_s46"
-[GOOD] (declare-fun s59 () Int) ; tracks user variable "__internal_sbv_s59"
-[GOOD] (declare-fun s72 () Int) ; tracks user variable "__internal_sbv_s72"
-[GOOD] (declare-fun s85 () Int) ; tracks user variable "__internal_sbv_s85"
-[GOOD] (declare-fun s98 () Int) ; tracks user variable "__internal_sbv_s98"
-[GOOD] (declare-fun s111 () Int) ; tracks user variable "__internal_sbv_s111"
-[GOOD] (declare-fun s124 () Int) ; tracks user variable "__internal_sbv_s124"
+[GOOD] (declare-fun s32 () Int) ; tracks user variable "__internal_sbv_s32"
+[GOOD] (declare-fun s44 () Int) ; tracks user variable "__internal_sbv_s44"
+[GOOD] (declare-fun s56 () Int) ; tracks user variable "__internal_sbv_s56"
+[GOOD] (declare-fun s68 () Int) ; tracks user variable "__internal_sbv_s68"
+[GOOD] (declare-fun s80 () Int) ; tracks user variable "__internal_sbv_s80"
+[GOOD] (declare-fun s92 () Int) ; tracks user variable "__internal_sbv_s92"
+[GOOD] (declare-fun s104 () Int) ; tracks user variable "__internal_sbv_s104"
+[GOOD] (declare-fun s116 () Int) ; tracks user variable "__internal_sbv_s116"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -37,223 +38,212 @@
 [GOOD] ; --- user given axioms ---
 [GOOD] ; --- formula ---
 [GOOD] (define-fun s2 () (Seq Int) (seq.unit s1))
-[GOOD] (define-fun s4 () Bool (= s0 s3))
-[GOOD] (define-fun s6 () (Seq Int) (seq.unit s5))
-[GOOD] (define-fun s7 () Int (seq.len s0))
-[GOOD] (define-fun s9 () Bool (> s7 s8))
-[GOOD] (define-fun s10 () Bool (not s9))
-[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s8 s11))
-[GOOD] (define-fun s13 () Bool (= s6 s12))
-[GOOD] (define-fun s14 () Bool (or s10 s13))
-[GOOD] (define-fun s15 () Int (+ s5 s11))
-[GOOD] (define-fun s16 () (Seq Int) (seq.unit s15))
-[GOOD] (define-fun s17 () Int (- s7 s11))
-[GOOD] (define-fun s18 () (Seq Int) (seq.extract s0 s11 s17))
-[GOOD] (define-fun s19 () Bool (= s3 s18))
+[GOOD] (define-fun s3 () Int (seq.len s0))
+[GOOD] (define-fun s5 () Bool (= s3 s4))
+[GOOD] (define-fun s8 () (Seq Int) (seq.unit s7))
+[GOOD] (define-fun s10 () (Seq Int) (seq.extract s0 s4 s9))
+[GOOD] (define-fun s11 () Bool (= s8 s10))
+[GOOD] (define-fun s12 () Bool (<= s3 s4))
+[GOOD] (define-fun s13 () Bool (or s11 s12))
+[GOOD] (define-fun s14 () Int (+ s7 s9))
+[GOOD] (define-fun s15 () (Seq Int) (seq.unit s14))
+[GOOD] (define-fun s16 () Int (- s3 s9))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s0 s9 s16))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (= s4 s18))
 [GOOD] (define-fun s21 () (Seq Int) (seq.unit s20))
-[GOOD] (define-fun s22 () Int (seq.len s18))
-[GOOD] (define-fun s23 () Bool (> s22 s8))
-[GOOD] (define-fun s24 () Bool (not s23))
-[GOOD] (define-fun s25 () (Seq Int) (seq.extract s18 s8 s11))
-[GOOD] (define-fun s26 () Bool (= s21 s25))
-[GOOD] (define-fun s27 () Bool (or s24 s26))
-[GOOD] (define-fun s28 () Int (+ s11 s20))
-[GOOD] (define-fun s29 () (Seq Int) (seq.unit s28))
-[GOOD] (define-fun s30 () Int (- s22 s11))
-[GOOD] (define-fun s31 () (Seq Int) (seq.extract s18 s11 s30))
-[GOOD] (define-fun s32 () Bool (= s3 s31))
-[GOOD] (define-fun s34 () (Seq Int) (seq.unit s33))
-[GOOD] (define-fun s35 () Int (seq.len s31))
-[GOOD] (define-fun s36 () Bool (> s35 s8))
-[GOOD] (define-fun s37 () Bool (not s36))
-[GOOD] (define-fun s38 () (Seq Int) (seq.extract s31 s8 s11))
-[GOOD] (define-fun s39 () Bool (= s34 s38))
-[GOOD] (define-fun s40 () Bool (or s37 s39))
-[GOOD] (define-fun s41 () Int (+ s11 s33))
-[GOOD] (define-fun s42 () (Seq Int) (seq.unit s41))
-[GOOD] (define-fun s43 () Int (- s35 s11))
-[GOOD] (define-fun s44 () (Seq Int) (seq.extract s31 s11 s43))
-[GOOD] (define-fun s45 () Bool (= s3 s44))
-[GOOD] (define-fun s47 () (Seq Int) (seq.unit s46))
-[GOOD] (define-fun s48 () Int (seq.len s44))
-[GOOD] (define-fun s49 () Bool (> s48 s8))
-[GOOD] (define-fun s50 () Bool (not s49))
-[GOOD] (define-fun s51 () (Seq Int) (seq.extract s44 s8 s11))
-[GOOD] (define-fun s52 () Bool (= s47 s51))
-[GOOD] (define-fun s53 () Bool (or s50 s52))
-[GOOD] (define-fun s54 () Int (+ s11 s46))
-[GOOD] (define-fun s55 () (Seq Int) (seq.unit s54))
-[GOOD] (define-fun s56 () Int (- s48 s11))
-[GOOD] (define-fun s57 () (Seq Int) (seq.extract s44 s11 s56))
-[GOOD] (define-fun s58 () Bool (= s3 s57))
-[GOOD] (define-fun s60 () (Seq Int) (seq.unit s59))
-[GOOD] (define-fun s61 () Int (seq.len s57))
-[GOOD] (define-fun s62 () Bool (> s61 s8))
-[GOOD] (define-fun s63 () Bool (not s62))
-[GOOD] (define-fun s64 () (Seq Int) (seq.extract s57 s8 s11))
-[GOOD] (define-fun s65 () Bool (= s60 s64))
-[GOOD] (define-fun s66 () Bool (or s63 s65))
-[GOOD] (define-fun s67 () Int (+ s11 s59))
-[GOOD] (define-fun s68 () (Seq Int) (seq.unit s67))
-[GOOD] (define-fun s69 () Int (- s61 s11))
-[GOOD] (define-fun s70 () (Seq Int) (seq.extract s57 s11 s69))
-[GOOD] (define-fun s71 () Bool (= s3 s70))
-[GOOD] (define-fun s73 () (Seq Int) (seq.unit s72))
-[GOOD] (define-fun s74 () Int (seq.len s70))
-[GOOD] (define-fun s75 () Bool (> s74 s8))
-[GOOD] (define-fun s76 () Bool (not s75))
-[GOOD] (define-fun s77 () (Seq Int) (seq.extract s70 s8 s11))
-[GOOD] (define-fun s78 () Bool (= s73 s77))
-[GOOD] (define-fun s79 () Bool (or s76 s78))
-[GOOD] (define-fun s80 () Int (+ s11 s72))
+[GOOD] (define-fun s22 () (Seq Int) (seq.extract s17 s4 s9))
+[GOOD] (define-fun s23 () Bool (= s21 s22))
+[GOOD] (define-fun s24 () Bool (<= s18 s4))
+[GOOD] (define-fun s25 () Bool (or s23 s24))
+[GOOD] (define-fun s26 () Int (+ s9 s20))
+[GOOD] (define-fun s27 () (Seq Int) (seq.unit s26))
+[GOOD] (define-fun s28 () Int (- s18 s9))
+[GOOD] (define-fun s29 () (Seq Int) (seq.extract s17 s9 s28))
+[GOOD] (define-fun s30 () Int (seq.len s29))
+[GOOD] (define-fun s31 () Bool (= s4 s30))
+[GOOD] (define-fun s33 () (Seq Int) (seq.unit s32))
+[GOOD] (define-fun s34 () (Seq Int) (seq.extract s29 s4 s9))
+[GOOD] (define-fun s35 () Bool (= s33 s34))
+[GOOD] (define-fun s36 () Bool (<= s30 s4))
+[GOOD] (define-fun s37 () Bool (or s35 s36))
+[GOOD] (define-fun s38 () Int (+ s9 s32))
+[GOOD] (define-fun s39 () (Seq Int) (seq.unit s38))
+[GOOD] (define-fun s40 () Int (- s30 s9))
+[GOOD] (define-fun s41 () (Seq Int) (seq.extract s29 s9 s40))
+[GOOD] (define-fun s42 () Int (seq.len s41))
+[GOOD] (define-fun s43 () Bool (= s4 s42))
+[GOOD] (define-fun s45 () (Seq Int) (seq.unit s44))
+[GOOD] (define-fun s46 () (Seq Int) (seq.extract s41 s4 s9))
+[GOOD] (define-fun s47 () Bool (= s45 s46))
+[GOOD] (define-fun s48 () Bool (<= s42 s4))
+[GOOD] (define-fun s49 () Bool (or s47 s48))
+[GOOD] (define-fun s50 () Int (+ s9 s44))
+[GOOD] (define-fun s51 () (Seq Int) (seq.unit s50))
+[GOOD] (define-fun s52 () Int (- s42 s9))
+[GOOD] (define-fun s53 () (Seq Int) (seq.extract s41 s9 s52))
+[GOOD] (define-fun s54 () Int (seq.len s53))
+[GOOD] (define-fun s55 () Bool (= s4 s54))
+[GOOD] (define-fun s57 () (Seq Int) (seq.unit s56))
+[GOOD] (define-fun s58 () (Seq Int) (seq.extract s53 s4 s9))
+[GOOD] (define-fun s59 () Bool (= s57 s58))
+[GOOD] (define-fun s60 () Bool (<= s54 s4))
+[GOOD] (define-fun s61 () Bool (or s59 s60))
+[GOOD] (define-fun s62 () Int (+ s9 s56))
+[GOOD] (define-fun s63 () (Seq Int) (seq.unit s62))
+[GOOD] (define-fun s64 () Int (- s54 s9))
+[GOOD] (define-fun s65 () (Seq Int) (seq.extract s53 s9 s64))
+[GOOD] (define-fun s66 () Int (seq.len s65))
+[GOOD] (define-fun s67 () Bool (= s4 s66))
+[GOOD] (define-fun s69 () (Seq Int) (seq.unit s68))
+[GOOD] (define-fun s70 () (Seq Int) (seq.extract s65 s4 s9))
+[GOOD] (define-fun s71 () Bool (= s69 s70))
+[GOOD] (define-fun s72 () Bool (<= s66 s4))
+[GOOD] (define-fun s73 () Bool (or s71 s72))
+[GOOD] (define-fun s74 () Int (+ s9 s68))
+[GOOD] (define-fun s75 () (Seq Int) (seq.unit s74))
+[GOOD] (define-fun s76 () Int (- s66 s9))
+[GOOD] (define-fun s77 () (Seq Int) (seq.extract s65 s9 s76))
+[GOOD] (define-fun s78 () Int (seq.len s77))
+[GOOD] (define-fun s79 () Bool (= s4 s78))
 [GOOD] (define-fun s81 () (Seq Int) (seq.unit s80))
-[GOOD] (define-fun s82 () Int (- s74 s11))
-[GOOD] (define-fun s83 () (Seq Int) (seq.extract s70 s11 s82))
-[GOOD] (define-fun s84 () Bool (= s3 s83))
-[GOOD] (define-fun s86 () (Seq Int) (seq.unit s85))
-[GOOD] (define-fun s87 () Int (seq.len s83))
-[GOOD] (define-fun s88 () Bool (> s87 s8))
-[GOOD] (define-fun s89 () Bool (not s88))
-[GOOD] (define-fun s90 () (Seq Int) (seq.extract s83 s8 s11))
-[GOOD] (define-fun s91 () Bool (= s86 s90))
-[GOOD] (define-fun s92 () Bool (or s89 s91))
-[GOOD] (define-fun s93 () Int (+ s11 s85))
-[GOOD] (define-fun s94 () (Seq Int) (seq.unit s93))
-[GOOD] (define-fun s95 () Int (- s87 s11))
-[GOOD] (define-fun s96 () (Seq Int) (seq.extract s83 s11 s95))
-[GOOD] (define-fun s97 () Bool (= s3 s96))
+[GOOD] (define-fun s82 () (Seq Int) (seq.extract s77 s4 s9))
+[GOOD] (define-fun s83 () Bool (= s81 s82))
+[GOOD] (define-fun s84 () Bool (<= s78 s4))
+[GOOD] (define-fun s85 () Bool (or s83 s84))
+[GOOD] (define-fun s86 () Int (+ s9 s80))
+[GOOD] (define-fun s87 () (Seq Int) (seq.unit s86))
+[GOOD] (define-fun s88 () Int (- s78 s9))
+[GOOD] (define-fun s89 () (Seq Int) (seq.extract s77 s9 s88))
+[GOOD] (define-fun s90 () Int (seq.len s89))
+[GOOD] (define-fun s91 () Bool (= s4 s90))
+[GOOD] (define-fun s93 () (Seq Int) (seq.unit s92))
+[GOOD] (define-fun s94 () (Seq Int) (seq.extract s89 s4 s9))
+[GOOD] (define-fun s95 () Bool (= s93 s94))
+[GOOD] (define-fun s96 () Bool (<= s90 s4))
+[GOOD] (define-fun s97 () Bool (or s95 s96))
+[GOOD] (define-fun s98 () Int (+ s9 s92))
 [GOOD] (define-fun s99 () (Seq Int) (seq.unit s98))
-[GOOD] (define-fun s100 () Int (seq.len s96))
-[GOOD] (define-fun s101 () Bool (> s100 s8))
-[GOOD] (define-fun s102 () Bool (not s101))
-[GOOD] (define-fun s103 () (Seq Int) (seq.extract s96 s8 s11))
-[GOOD] (define-fun s104 () Bool (= s99 s103))
-[GOOD] (define-fun s105 () Bool (or s102 s104))
-[GOOD] (define-fun s106 () Int (+ s11 s98))
-[GOOD] (define-fun s107 () (Seq Int) (seq.unit s106))
-[GOOD] (define-fun s108 () Int (- s100 s11))
-[GOOD] (define-fun s109 () (Seq Int) (seq.extract s96 s11 s108))
-[GOOD] (define-fun s110 () Bool (= s3 s109))
-[GOOD] (define-fun s112 () (Seq Int) (seq.unit s111))
-[GOOD] (define-fun s113 () Int (seq.len s109))
-[GOOD] (define-fun s114 () Bool (> s113 s8))
-[GOOD] (define-fun s115 () Bool (not s114))
-[GOOD] (define-fun s116 () (Seq Int) (seq.extract s109 s8 s11))
-[GOOD] (define-fun s117 () Bool (= s112 s116))
-[GOOD] (define-fun s118 () Bool (or s115 s117))
-[GOOD] (define-fun s119 () Int (+ s11 s111))
-[GOOD] (define-fun s120 () (Seq Int) (seq.unit s119))
-[GOOD] (define-fun s121 () Int (- s113 s11))
-[GOOD] (define-fun s122 () (Seq Int) (seq.extract s109 s11 s121))
-[GOOD] (define-fun s123 () Bool (= s3 s122))
-[GOOD] (define-fun s125 () (Seq Int) (seq.unit s124))
-[GOOD] (define-fun s126 () Int (seq.len s122))
-[GOOD] (define-fun s127 () Bool (> s126 s8))
-[GOOD] (define-fun s128 () Bool (not s127))
-[GOOD] (define-fun s129 () (Seq Int) (seq.extract s122 s8 s11))
-[GOOD] (define-fun s130 () Bool (= s125 s129))
-[GOOD] (define-fun s131 () Bool (or s128 s130))
-[GOOD] (define-fun s132 () Int (+ s11 s124))
-[GOOD] (define-fun s133 () (Seq Int) (seq.unit s132))
-[GOOD] (define-fun s134 () (Seq Int) (ite s123 s3 s133))
-[GOOD] (define-fun s135 () (Seq Int) (seq.++ s120 s134))
-[GOOD] (define-fun s136 () (Seq Int) (ite s110 s3 s135))
-[GOOD] (define-fun s137 () (Seq Int) (seq.++ s107 s136))
-[GOOD] (define-fun s138 () (Seq Int) (ite s97 s3 s137))
-[GOOD] (define-fun s139 () (Seq Int) (seq.++ s94 s138))
-[GOOD] (define-fun s140 () (Seq Int) (ite s84 s3 s139))
-[GOOD] (define-fun s141 () (Seq Int) (seq.++ s81 s140))
-[GOOD] (define-fun s142 () (Seq Int) (ite s71 s3 s141))
-[GOOD] (define-fun s143 () (Seq Int) (seq.++ s68 s142))
-[GOOD] (define-fun s144 () (Seq Int) (ite s58 s3 s143))
-[GOOD] (define-fun s145 () (Seq Int) (seq.++ s55 s144))
-[GOOD] (define-fun s146 () (Seq Int) (ite s45 s3 s145))
-[GOOD] (define-fun s147 () (Seq Int) (seq.++ s42 s146))
-[GOOD] (define-fun s148 () (Seq Int) (ite s32 s3 s147))
-[GOOD] (define-fun s149 () (Seq Int) (seq.++ s29 s148))
-[GOOD] (define-fun s150 () (Seq Int) (ite s19 s3 s149))
-[GOOD] (define-fun s151 () (Seq Int) (seq.++ s16 s150))
-[GOOD] (define-fun s152 () (Seq Int) (ite s4 s3 s151))
-[GOOD] (define-fun s153 () Int (seq.len s152))
-[GOOD] (define-fun s155 () Bool (> s153 s154))
-[GOOD] (define-fun s156 () Bool (not s155))
-[GOOD] (define-fun s157 () (Seq Int) (seq.extract s152 s154 s11))
-[GOOD] (define-fun s158 () Bool (= s2 s157))
-[GOOD] (define-fun s159 () Bool (or s156 s158))
-[GOOD] (define-fun s161 () Bool (> s1 s160))
-[GOOD] (define-fun s162 () Bool (not s161))
-[GOOD] (define-fun s163 () Bool (< s124 s8))
-[GOOD] (define-fun s165 () Bool (> s124 s164))
-[GOOD] (define-fun s166 () Bool (or s163 s165))
-[GOOD] (define-fun s167 () Bool (not s123))
-[GOOD] (define-fun s168 () Bool (and s166 s167))
-[GOOD] (define-fun s169 () Bool (< s111 s8))
-[GOOD] (define-fun s170 () Bool (> s111 s164))
-[GOOD] (define-fun s171 () Bool (or s169 s170))
-[GOOD] (define-fun s172 () Bool (or s168 s171))
-[GOOD] (define-fun s173 () Bool (not s110))
-[GOOD] (define-fun s174 () Bool (and s172 s173))
-[GOOD] (define-fun s175 () Bool (< s98 s8))
-[GOOD] (define-fun s176 () Bool (> s98 s164))
-[GOOD] (define-fun s177 () Bool (or s175 s176))
-[GOOD] (define-fun s178 () Bool (or s174 s177))
-[GOOD] (define-fun s179 () Bool (not s97))
-[GOOD] (define-fun s180 () Bool (and s178 s179))
-[GOOD] (define-fun s181 () Bool (< s85 s8))
-[GOOD] (define-fun s182 () Bool (> s85 s164))
-[GOOD] (define-fun s183 () Bool (or s181 s182))
-[GOOD] (define-fun s184 () Bool (or s180 s183))
-[GOOD] (define-fun s185 () Bool (not s84))
-[GOOD] (define-fun s186 () Bool (and s184 s185))
-[GOOD] (define-fun s187 () Bool (< s72 s8))
-[GOOD] (define-fun s188 () Bool (> s72 s164))
-[GOOD] (define-fun s189 () Bool (or s187 s188))
-[GOOD] (define-fun s190 () Bool (or s186 s189))
-[GOOD] (define-fun s191 () Bool (not s71))
-[GOOD] (define-fun s192 () Bool (and s190 s191))
-[GOOD] (define-fun s193 () Bool (< s59 s8))
-[GOOD] (define-fun s194 () Bool (> s59 s164))
-[GOOD] (define-fun s195 () Bool (or s193 s194))
-[GOOD] (define-fun s196 () Bool (or s192 s195))
-[GOOD] (define-fun s197 () Bool (not s58))
-[GOOD] (define-fun s198 () Bool (and s196 s197))
-[GOOD] (define-fun s199 () Bool (< s46 s8))
-[GOOD] (define-fun s200 () Bool (> s46 s164))
-[GOOD] (define-fun s201 () Bool (or s199 s200))
-[GOOD] (define-fun s202 () Bool (or s198 s201))
-[GOOD] (define-fun s203 () Bool (not s45))
-[GOOD] (define-fun s204 () Bool (and s202 s203))
-[GOOD] (define-fun s205 () Bool (< s33 s8))
-[GOOD] (define-fun s206 () Bool (> s33 s164))
-[GOOD] (define-fun s207 () Bool (or s205 s206))
-[GOOD] (define-fun s208 () Bool (or s204 s207))
-[GOOD] (define-fun s209 () Bool (not s32))
-[GOOD] (define-fun s210 () Bool (and s208 s209))
-[GOOD] (define-fun s211 () Bool (< s20 s8))
-[GOOD] (define-fun s212 () Bool (> s20 s164))
-[GOOD] (define-fun s213 () Bool (or s211 s212))
-[GOOD] (define-fun s214 () Bool (or s210 s213))
-[GOOD] (define-fun s215 () Bool (not s19))
-[GOOD] (define-fun s216 () Bool (and s214 s215))
-[GOOD] (define-fun s217 () Bool (< s5 s8))
-[GOOD] (define-fun s218 () Bool (> s5 s164))
-[GOOD] (define-fun s219 () Bool (or s217 s218))
-[GOOD] (define-fun s220 () Bool (or s216 s219))
-[GOOD] (define-fun s221 () Bool (not s4))
-[GOOD] (define-fun s222 () Bool (and s220 s221))
-[GOOD] (define-fun s223 () Bool (or s162 s222))
-[GOOD] (assert s14)
-[GOOD] (assert s27)
-[GOOD] (assert s40)
-[GOOD] (assert s53)
-[GOOD] (assert s66)
-[GOOD] (assert s79)
-[GOOD] (assert s92)
-[GOOD] (assert s105)
-[GOOD] (assert s118)
-[GOOD] (assert s131)
-[GOOD] (assert s159)
-[GOOD] (assert s223)
+[GOOD] (define-fun s100 () Int (- s90 s9))
+[GOOD] (define-fun s101 () (Seq Int) (seq.extract s89 s9 s100))
+[GOOD] (define-fun s102 () Int (seq.len s101))
+[GOOD] (define-fun s103 () Bool (= s4 s102))
+[GOOD] (define-fun s105 () (Seq Int) (seq.unit s104))
+[GOOD] (define-fun s106 () (Seq Int) (seq.extract s101 s4 s9))
+[GOOD] (define-fun s107 () Bool (= s105 s106))
+[GOOD] (define-fun s108 () Bool (<= s102 s4))
+[GOOD] (define-fun s109 () Bool (or s107 s108))
+[GOOD] (define-fun s110 () Int (+ s9 s104))
+[GOOD] (define-fun s111 () (Seq Int) (seq.unit s110))
+[GOOD] (define-fun s112 () Int (- s102 s9))
+[GOOD] (define-fun s113 () (Seq Int) (seq.extract s101 s9 s112))
+[GOOD] (define-fun s114 () Int (seq.len s113))
+[GOOD] (define-fun s115 () Bool (= s4 s114))
+[GOOD] (define-fun s117 () (Seq Int) (seq.unit s116))
+[GOOD] (define-fun s118 () (Seq Int) (seq.extract s113 s4 s9))
+[GOOD] (define-fun s119 () Bool (= s117 s118))
+[GOOD] (define-fun s120 () Bool (<= s114 s4))
+[GOOD] (define-fun s121 () Bool (or s119 s120))
+[GOOD] (define-fun s122 () Int (+ s9 s116))
+[GOOD] (define-fun s123 () (Seq Int) (seq.unit s122))
+[GOOD] (define-fun s124 () (Seq Int) (ite s115 s6 s123))
+[GOOD] (define-fun s125 () (Seq Int) (seq.++ s111 s124))
+[GOOD] (define-fun s126 () (Seq Int) (ite s103 s6 s125))
+[GOOD] (define-fun s127 () (Seq Int) (seq.++ s99 s126))
+[GOOD] (define-fun s128 () (Seq Int) (ite s91 s6 s127))
+[GOOD] (define-fun s129 () (Seq Int) (seq.++ s87 s128))
+[GOOD] (define-fun s130 () (Seq Int) (ite s79 s6 s129))
+[GOOD] (define-fun s131 () (Seq Int) (seq.++ s75 s130))
+[GOOD] (define-fun s132 () (Seq Int) (ite s67 s6 s131))
+[GOOD] (define-fun s133 () (Seq Int) (seq.++ s63 s132))
+[GOOD] (define-fun s134 () (Seq Int) (ite s55 s6 s133))
+[GOOD] (define-fun s135 () (Seq Int) (seq.++ s51 s134))
+[GOOD] (define-fun s136 () (Seq Int) (ite s43 s6 s135))
+[GOOD] (define-fun s137 () (Seq Int) (seq.++ s39 s136))
+[GOOD] (define-fun s138 () (Seq Int) (ite s31 s6 s137))
+[GOOD] (define-fun s139 () (Seq Int) (seq.++ s27 s138))
+[GOOD] (define-fun s140 () (Seq Int) (ite s19 s6 s139))
+[GOOD] (define-fun s141 () (Seq Int) (seq.++ s15 s140))
+[GOOD] (define-fun s142 () (Seq Int) (ite s5 s6 s141))
+[GOOD] (define-fun s144 () (Seq Int) (seq.extract s142 s143 s9))
+[GOOD] (define-fun s145 () Bool (= s2 s144))
+[GOOD] (define-fun s146 () Int (seq.len s142))
+[GOOD] (define-fun s147 () Bool (<= s146 s143))
+[GOOD] (define-fun s148 () Bool (or s145 s147))
+[GOOD] (define-fun s150 () Bool (> s1 s149))
+[GOOD] (define-fun s151 () Bool (not s150))
+[GOOD] (define-fun s152 () Bool (< s116 s4))
+[GOOD] (define-fun s154 () Bool (> s116 s153))
+[GOOD] (define-fun s155 () Bool (or s152 s154))
+[GOOD] (define-fun s156 () Bool (not s115))
+[GOOD] (define-fun s157 () Bool (and s155 s156))
+[GOOD] (define-fun s158 () Bool (< s104 s4))
+[GOOD] (define-fun s159 () Bool (> s104 s153))
+[GOOD] (define-fun s160 () Bool (or s158 s159))
+[GOOD] (define-fun s161 () Bool (or s157 s160))
+[GOOD] (define-fun s162 () Bool (not s103))
+[GOOD] (define-fun s163 () Bool (and s161 s162))
+[GOOD] (define-fun s164 () Bool (< s92 s4))
+[GOOD] (define-fun s165 () Bool (> s92 s153))
+[GOOD] (define-fun s166 () Bool (or s164 s165))
+[GOOD] (define-fun s167 () Bool (or s163 s166))
+[GOOD] (define-fun s168 () Bool (not s91))
+[GOOD] (define-fun s169 () Bool (and s167 s168))
+[GOOD] (define-fun s170 () Bool (< s80 s4))
+[GOOD] (define-fun s171 () Bool (> s80 s153))
+[GOOD] (define-fun s172 () Bool (or s170 s171))
+[GOOD] (define-fun s173 () Bool (or s169 s172))
+[GOOD] (define-fun s174 () Bool (not s79))
+[GOOD] (define-fun s175 () Bool (and s173 s174))
+[GOOD] (define-fun s176 () Bool (< s68 s4))
+[GOOD] (define-fun s177 () Bool (> s68 s153))
+[GOOD] (define-fun s178 () Bool (or s176 s177))
+[GOOD] (define-fun s179 () Bool (or s175 s178))
+[GOOD] (define-fun s180 () Bool (not s67))
+[GOOD] (define-fun s181 () Bool (and s179 s180))
+[GOOD] (define-fun s182 () Bool (< s56 s4))
+[GOOD] (define-fun s183 () Bool (> s56 s153))
+[GOOD] (define-fun s184 () Bool (or s182 s183))
+[GOOD] (define-fun s185 () Bool (or s181 s184))
+[GOOD] (define-fun s186 () Bool (not s55))
+[GOOD] (define-fun s187 () Bool (and s185 s186))
+[GOOD] (define-fun s188 () Bool (< s44 s4))
+[GOOD] (define-fun s189 () Bool (> s44 s153))
+[GOOD] (define-fun s190 () Bool (or s188 s189))
+[GOOD] (define-fun s191 () Bool (or s187 s190))
+[GOOD] (define-fun s192 () Bool (not s43))
+[GOOD] (define-fun s193 () Bool (and s191 s192))
+[GOOD] (define-fun s194 () Bool (< s32 s4))
+[GOOD] (define-fun s195 () Bool (> s32 s153))
+[GOOD] (define-fun s196 () Bool (or s194 s195))
+[GOOD] (define-fun s197 () Bool (or s193 s196))
+[GOOD] (define-fun s198 () Bool (not s31))
+[GOOD] (define-fun s199 () Bool (and s197 s198))
+[GOOD] (define-fun s200 () Bool (< s20 s4))
+[GOOD] (define-fun s201 () Bool (> s20 s153))
+[GOOD] (define-fun s202 () Bool (or s200 s201))
+[GOOD] (define-fun s203 () Bool (or s199 s202))
+[GOOD] (define-fun s204 () Bool (not s19))
+[GOOD] (define-fun s205 () Bool (and s203 s204))
+[GOOD] (define-fun s206 () Bool (< s7 s4))
+[GOOD] (define-fun s207 () Bool (> s7 s153))
+[GOOD] (define-fun s208 () Bool (or s206 s207))
+[GOOD] (define-fun s209 () Bool (or s205 s208))
+[GOOD] (define-fun s210 () Bool (not s5))
+[GOOD] (define-fun s211 () Bool (and s209 s210))
+[GOOD] (define-fun s212 () Bool (or s151 s211))
+[GOOD] (assert s13)
+[GOOD] (assert s25)
+[GOOD] (assert s37)
+[GOOD] (assert s49)
+[GOOD] (assert s61)
+[GOOD] (assert s73)
+[GOOD] (assert s85)
+[GOOD] (assert s97)
+[GOOD] (assert s109)
+[GOOD] (assert s121)
+[GOOD] (assert s148)
+[GOOD] (assert s212)
 [SEND] (check-sat)
 [RECV] sat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/maxlWithFailure.gold b/SBVTestSuite/GoldFiles/maxlWithFailure.gold
--- a/SBVTestSuite/GoldFiles/maxlWithFailure.gold
+++ b/SBVTestSuite/GoldFiles/maxlWithFailure.gold
@@ -10,221 +10,211 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s3 () Int 0)
+[GOOD] (define-fun s2 () Int 0)
 [GOOD] (define-fun s4 () Int 1)
-[GOOD] (define-fun s142 () Int 10)
-[GOOD] (define-fun s1 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s131 () Int 10)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "ints"
 [GOOD] (declare-fun s9 () Int) ; tracks user variable "__internal_sbv_s9"
-[GOOD] (declare-fun s22 () Int) ; tracks user variable "__internal_sbv_s22"
-[GOOD] (declare-fun s35 () Int) ; tracks user variable "__internal_sbv_s35"
-[GOOD] (declare-fun s48 () Int) ; tracks user variable "__internal_sbv_s48"
-[GOOD] (declare-fun s61 () Int) ; tracks user variable "__internal_sbv_s61"
-[GOOD] (declare-fun s74 () Int) ; tracks user variable "__internal_sbv_s74"
-[GOOD] (declare-fun s87 () Int) ; tracks user variable "__internal_sbv_s87"
-[GOOD] (declare-fun s100 () Int) ; tracks user variable "__internal_sbv_s100"
+[GOOD] (declare-fun s21 () Int) ; tracks user variable "__internal_sbv_s21"
+[GOOD] (declare-fun s33 () Int) ; tracks user variable "__internal_sbv_s33"
+[GOOD] (declare-fun s45 () Int) ; tracks user variable "__internal_sbv_s45"
+[GOOD] (declare-fun s57 () Int) ; tracks user variable "__internal_sbv_s57"
+[GOOD] (declare-fun s69 () Int) ; tracks user variable "__internal_sbv_s69"
+[GOOD] (declare-fun s81 () Int) ; tracks user variable "__internal_sbv_s81"
+[GOOD] (declare-fun s93 () Int) ; tracks user variable "__internal_sbv_s93"
+[GOOD] (declare-fun s105 () Int) ; tracks user variable "__internal_sbv_s105"
 [GOOD] (declare-fun s113 () Int) ; tracks user variable "__internal_sbv_s113"
-[GOOD] (declare-fun s122 () Int) ; tracks user variable "__internal_sbv_s122"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user given axioms ---
 [GOOD] ; --- formula ---
-[GOOD] (define-fun s2 () Bool (= s0 s1))
-[GOOD] (define-fun s5 () Int (seq.len s0))
-[GOOD] (define-fun s6 () Int (- s5 s4))
-[GOOD] (define-fun s7 () (Seq Int) (seq.extract s0 s4 s6))
-[GOOD] (define-fun s8 () Bool (= s1 s7))
+[GOOD] (define-fun s1 () Int (seq.len s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () Int (- s1 s4))
+[GOOD] (define-fun s6 () (Seq Int) (seq.extract s0 s4 s5))
+[GOOD] (define-fun s7 () Int (seq.len s6))
+[GOOD] (define-fun s8 () Bool (= s2 s7))
 [GOOD] (define-fun s10 () (Seq Int) (seq.unit s9))
-[GOOD] (define-fun s11 () Bool (> s5 s3))
-[GOOD] (define-fun s12 () Bool (not s11))
-[GOOD] (define-fun s13 () (Seq Int) (seq.extract s0 s3 s4))
-[GOOD] (define-fun s14 () Bool (= s10 s13))
-[GOOD] (define-fun s15 () Bool (or s12 s14))
-[GOOD] (define-fun s16 () Bool (<= s9 s3))
-[GOOD] (define-fun s17 () Int (ite s16 s3 s9))
-[GOOD] (define-fun s18 () Int (seq.len s7))
-[GOOD] (define-fun s19 () Int (- s18 s4))
-[GOOD] (define-fun s20 () (Seq Int) (seq.extract s7 s4 s19))
-[GOOD] (define-fun s21 () Bool (= s1 s20))
-[GOOD] (define-fun s23 () (Seq Int) (seq.unit s22))
-[GOOD] (define-fun s24 () Bool (> s18 s3))
-[GOOD] (define-fun s25 () Bool (not s24))
-[GOOD] (define-fun s26 () (Seq Int) (seq.extract s7 s3 s4))
-[GOOD] (define-fun s27 () Bool (= s23 s26))
-[GOOD] (define-fun s28 () Bool (or s25 s27))
-[GOOD] (define-fun s29 () Bool (<= s22 s17))
-[GOOD] (define-fun s30 () Int (ite s29 s17 s22))
-[GOOD] (define-fun s31 () Int (seq.len s20))
-[GOOD] (define-fun s32 () Int (- s31 s4))
-[GOOD] (define-fun s33 () (Seq Int) (seq.extract s20 s4 s32))
-[GOOD] (define-fun s34 () Bool (= s1 s33))
-[GOOD] (define-fun s36 () (Seq Int) (seq.unit s35))
-[GOOD] (define-fun s37 () Bool (> s31 s3))
-[GOOD] (define-fun s38 () Bool (not s37))
-[GOOD] (define-fun s39 () (Seq Int) (seq.extract s20 s3 s4))
-[GOOD] (define-fun s40 () Bool (= s36 s39))
-[GOOD] (define-fun s41 () Bool (or s38 s40))
-[GOOD] (define-fun s42 () Bool (<= s35 s30))
-[GOOD] (define-fun s43 () Int (ite s42 s30 s35))
-[GOOD] (define-fun s44 () Int (seq.len s33))
-[GOOD] (define-fun s45 () Int (- s44 s4))
-[GOOD] (define-fun s46 () (Seq Int) (seq.extract s33 s4 s45))
-[GOOD] (define-fun s47 () Bool (= s1 s46))
-[GOOD] (define-fun s49 () (Seq Int) (seq.unit s48))
-[GOOD] (define-fun s50 () Bool (> s44 s3))
-[GOOD] (define-fun s51 () Bool (not s50))
-[GOOD] (define-fun s52 () (Seq Int) (seq.extract s33 s3 s4))
-[GOOD] (define-fun s53 () Bool (= s49 s52))
-[GOOD] (define-fun s54 () Bool (or s51 s53))
-[GOOD] (define-fun s55 () Bool (<= s48 s43))
-[GOOD] (define-fun s56 () Int (ite s55 s43 s48))
-[GOOD] (define-fun s57 () Int (seq.len s46))
-[GOOD] (define-fun s58 () Int (- s57 s4))
-[GOOD] (define-fun s59 () (Seq Int) (seq.extract s46 s4 s58))
-[GOOD] (define-fun s60 () Bool (= s1 s59))
-[GOOD] (define-fun s62 () (Seq Int) (seq.unit s61))
-[GOOD] (define-fun s63 () Bool (> s57 s3))
-[GOOD] (define-fun s64 () Bool (not s63))
-[GOOD] (define-fun s65 () (Seq Int) (seq.extract s46 s3 s4))
-[GOOD] (define-fun s66 () Bool (= s62 s65))
-[GOOD] (define-fun s67 () Bool (or s64 s66))
-[GOOD] (define-fun s68 () Bool (<= s61 s56))
-[GOOD] (define-fun s69 () Int (ite s68 s56 s61))
-[GOOD] (define-fun s70 () Int (seq.len s59))
-[GOOD] (define-fun s71 () Int (- s70 s4))
-[GOOD] (define-fun s72 () (Seq Int) (seq.extract s59 s4 s71))
-[GOOD] (define-fun s73 () Bool (= s1 s72))
-[GOOD] (define-fun s75 () (Seq Int) (seq.unit s74))
-[GOOD] (define-fun s76 () Bool (> s70 s3))
-[GOOD] (define-fun s77 () Bool (not s76))
-[GOOD] (define-fun s78 () (Seq Int) (seq.extract s59 s3 s4))
-[GOOD] (define-fun s79 () Bool (= s75 s78))
-[GOOD] (define-fun s80 () Bool (or s77 s79))
-[GOOD] (define-fun s81 () Bool (<= s74 s69))
-[GOOD] (define-fun s82 () Int (ite s81 s69 s74))
-[GOOD] (define-fun s83 () Int (seq.len s72))
-[GOOD] (define-fun s84 () Int (- s83 s4))
-[GOOD] (define-fun s85 () (Seq Int) (seq.extract s72 s4 s84))
-[GOOD] (define-fun s86 () Bool (= s1 s85))
-[GOOD] (define-fun s88 () (Seq Int) (seq.unit s87))
-[GOOD] (define-fun s89 () Bool (> s83 s3))
-[GOOD] (define-fun s90 () Bool (not s89))
-[GOOD] (define-fun s91 () (Seq Int) (seq.extract s72 s3 s4))
-[GOOD] (define-fun s92 () Bool (= s88 s91))
-[GOOD] (define-fun s93 () Bool (or s90 s92))
-[GOOD] (define-fun s94 () Bool (<= s87 s82))
-[GOOD] (define-fun s95 () Int (ite s94 s82 s87))
-[GOOD] (define-fun s96 () Int (seq.len s85))
-[GOOD] (define-fun s97 () Int (- s96 s4))
-[GOOD] (define-fun s98 () (Seq Int) (seq.extract s85 s4 s97))
-[GOOD] (define-fun s99 () Bool (= s1 s98))
-[GOOD] (define-fun s101 () (Seq Int) (seq.unit s100))
-[GOOD] (define-fun s102 () Bool (> s96 s3))
-[GOOD] (define-fun s103 () Bool (not s102))
-[GOOD] (define-fun s104 () (Seq Int) (seq.extract s85 s3 s4))
-[GOOD] (define-fun s105 () Bool (= s101 s104))
-[GOOD] (define-fun s106 () Bool (or s103 s105))
-[GOOD] (define-fun s107 () Bool (<= s100 s95))
-[GOOD] (define-fun s108 () Int (ite s107 s95 s100))
-[GOOD] (define-fun s109 () Int (seq.len s98))
-[GOOD] (define-fun s110 () Int (- s109 s4))
-[GOOD] (define-fun s111 () (Seq Int) (seq.extract s98 s4 s110))
-[GOOD] (define-fun s112 () Bool (= s1 s111))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s0 s2 s4))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s13 () Bool (<= s1 s2))
+[GOOD] (define-fun s14 () Bool (or s12 s13))
+[GOOD] (define-fun s15 () Bool (<= s9 s2))
+[GOOD] (define-fun s16 () Int (ite s15 s2 s9))
+[GOOD] (define-fun s17 () Int (- s7 s4))
+[GOOD] (define-fun s18 () (Seq Int) (seq.extract s6 s4 s17))
+[GOOD] (define-fun s19 () Int (seq.len s18))
+[GOOD] (define-fun s20 () Bool (= s2 s19))
+[GOOD] (define-fun s22 () (Seq Int) (seq.unit s21))
+[GOOD] (define-fun s23 () (Seq Int) (seq.extract s6 s2 s4))
+[GOOD] (define-fun s24 () Bool (= s22 s23))
+[GOOD] (define-fun s25 () Bool (<= s7 s2))
+[GOOD] (define-fun s26 () Bool (or s24 s25))
+[GOOD] (define-fun s27 () Bool (<= s21 s16))
+[GOOD] (define-fun s28 () Int (ite s27 s16 s21))
+[GOOD] (define-fun s29 () Int (- s19 s4))
+[GOOD] (define-fun s30 () (Seq Int) (seq.extract s18 s4 s29))
+[GOOD] (define-fun s31 () Int (seq.len s30))
+[GOOD] (define-fun s32 () Bool (= s2 s31))
+[GOOD] (define-fun s34 () (Seq Int) (seq.unit s33))
+[GOOD] (define-fun s35 () (Seq Int) (seq.extract s18 s2 s4))
+[GOOD] (define-fun s36 () Bool (= s34 s35))
+[GOOD] (define-fun s37 () Bool (<= s19 s2))
+[GOOD] (define-fun s38 () Bool (or s36 s37))
+[GOOD] (define-fun s39 () Bool (<= s33 s28))
+[GOOD] (define-fun s40 () Int (ite s39 s28 s33))
+[GOOD] (define-fun s41 () Int (- s31 s4))
+[GOOD] (define-fun s42 () (Seq Int) (seq.extract s30 s4 s41))
+[GOOD] (define-fun s43 () Int (seq.len s42))
+[GOOD] (define-fun s44 () Bool (= s2 s43))
+[GOOD] (define-fun s46 () (Seq Int) (seq.unit s45))
+[GOOD] (define-fun s47 () (Seq Int) (seq.extract s30 s2 s4))
+[GOOD] (define-fun s48 () Bool (= s46 s47))
+[GOOD] (define-fun s49 () Bool (<= s31 s2))
+[GOOD] (define-fun s50 () Bool (or s48 s49))
+[GOOD] (define-fun s51 () Bool (<= s45 s40))
+[GOOD] (define-fun s52 () Int (ite s51 s40 s45))
+[GOOD] (define-fun s53 () Int (- s43 s4))
+[GOOD] (define-fun s54 () (Seq Int) (seq.extract s42 s4 s53))
+[GOOD] (define-fun s55 () Int (seq.len s54))
+[GOOD] (define-fun s56 () Bool (= s2 s55))
+[GOOD] (define-fun s58 () (Seq Int) (seq.unit s57))
+[GOOD] (define-fun s59 () (Seq Int) (seq.extract s42 s2 s4))
+[GOOD] (define-fun s60 () Bool (= s58 s59))
+[GOOD] (define-fun s61 () Bool (<= s43 s2))
+[GOOD] (define-fun s62 () Bool (or s60 s61))
+[GOOD] (define-fun s63 () Bool (<= s57 s52))
+[GOOD] (define-fun s64 () Int (ite s63 s52 s57))
+[GOOD] (define-fun s65 () Int (- s55 s4))
+[GOOD] (define-fun s66 () (Seq Int) (seq.extract s54 s4 s65))
+[GOOD] (define-fun s67 () Int (seq.len s66))
+[GOOD] (define-fun s68 () Bool (= s2 s67))
+[GOOD] (define-fun s70 () (Seq Int) (seq.unit s69))
+[GOOD] (define-fun s71 () (Seq Int) (seq.extract s54 s2 s4))
+[GOOD] (define-fun s72 () Bool (= s70 s71))
+[GOOD] (define-fun s73 () Bool (<= s55 s2))
+[GOOD] (define-fun s74 () Bool (or s72 s73))
+[GOOD] (define-fun s75 () Bool (<= s69 s64))
+[GOOD] (define-fun s76 () Int (ite s75 s64 s69))
+[GOOD] (define-fun s77 () Int (- s67 s4))
+[GOOD] (define-fun s78 () (Seq Int) (seq.extract s66 s4 s77))
+[GOOD] (define-fun s79 () Int (seq.len s78))
+[GOOD] (define-fun s80 () Bool (= s2 s79))
+[GOOD] (define-fun s82 () (Seq Int) (seq.unit s81))
+[GOOD] (define-fun s83 () (Seq Int) (seq.extract s66 s2 s4))
+[GOOD] (define-fun s84 () Bool (= s82 s83))
+[GOOD] (define-fun s85 () Bool (<= s67 s2))
+[GOOD] (define-fun s86 () Bool (or s84 s85))
+[GOOD] (define-fun s87 () Bool (<= s81 s76))
+[GOOD] (define-fun s88 () Int (ite s87 s76 s81))
+[GOOD] (define-fun s89 () Int (- s79 s4))
+[GOOD] (define-fun s90 () (Seq Int) (seq.extract s78 s4 s89))
+[GOOD] (define-fun s91 () Int (seq.len s90))
+[GOOD] (define-fun s92 () Bool (= s2 s91))
+[GOOD] (define-fun s94 () (Seq Int) (seq.unit s93))
+[GOOD] (define-fun s95 () (Seq Int) (seq.extract s78 s2 s4))
+[GOOD] (define-fun s96 () Bool (= s94 s95))
+[GOOD] (define-fun s97 () Bool (<= s79 s2))
+[GOOD] (define-fun s98 () Bool (or s96 s97))
+[GOOD] (define-fun s99 () Bool (<= s93 s88))
+[GOOD] (define-fun s100 () Int (ite s99 s88 s93))
+[GOOD] (define-fun s101 () Int (- s91 s4))
+[GOOD] (define-fun s102 () (Seq Int) (seq.extract s90 s4 s101))
+[GOOD] (define-fun s103 () Int (seq.len s102))
+[GOOD] (define-fun s104 () Bool (= s2 s103))
+[GOOD] (define-fun s106 () (Seq Int) (seq.unit s105))
+[GOOD] (define-fun s107 () (Seq Int) (seq.extract s90 s2 s4))
+[GOOD] (define-fun s108 () Bool (= s106 s107))
+[GOOD] (define-fun s109 () Bool (<= s91 s2))
+[GOOD] (define-fun s110 () Bool (or s108 s109))
+[GOOD] (define-fun s111 () Bool (<= s105 s100))
+[GOOD] (define-fun s112 () Int (ite s111 s100 s105))
 [GOOD] (define-fun s114 () (Seq Int) (seq.unit s113))
-[GOOD] (define-fun s115 () Bool (> s109 s3))
-[GOOD] (define-fun s116 () Bool (not s115))
-[GOOD] (define-fun s117 () (Seq Int) (seq.extract s98 s3 s4))
-[GOOD] (define-fun s118 () Bool (= s114 s117))
-[GOOD] (define-fun s119 () Bool (or s116 s118))
-[GOOD] (define-fun s120 () Bool (<= s113 s108))
-[GOOD] (define-fun s121 () Int (ite s120 s108 s113))
-[GOOD] (define-fun s123 () (Seq Int) (seq.unit s122))
-[GOOD] (define-fun s124 () Int (seq.len s111))
-[GOOD] (define-fun s125 () Bool (> s124 s3))
-[GOOD] (define-fun s126 () Bool (not s125))
-[GOOD] (define-fun s127 () (Seq Int) (seq.extract s111 s3 s4))
-[GOOD] (define-fun s128 () Bool (= s123 s127))
-[GOOD] (define-fun s129 () Bool (or s126 s128))
-[GOOD] (define-fun s130 () Bool (<= s122 s121))
-[GOOD] (define-fun s131 () Int (ite s130 s121 s122))
-[GOOD] (define-fun s132 () Int (ite s112 s121 s131))
-[GOOD] (define-fun s133 () Int (ite s99 s108 s132))
-[GOOD] (define-fun s134 () Int (ite s86 s95 s133))
-[GOOD] (define-fun s135 () Int (ite s73 s82 s134))
-[GOOD] (define-fun s136 () Int (ite s60 s69 s135))
-[GOOD] (define-fun s137 () Int (ite s47 s56 s136))
-[GOOD] (define-fun s138 () Int (ite s34 s43 s137))
-[GOOD] (define-fun s139 () Int (ite s21 s30 s138))
-[GOOD] (define-fun s140 () Int (ite s8 s17 s139))
-[GOOD] (define-fun s141 () Int (ite s2 s3 s140))
-[GOOD] (define-fun s143 () Bool (> s141 s142))
-[GOOD] (define-fun s144 () Bool (not s143))
-[GOOD] (define-fun s145 () Bool (< s9 s3))
-[GOOD] (define-fun s146 () Bool (> s9 s142))
+[GOOD] (define-fun s115 () (Seq Int) (seq.extract s102 s2 s4))
+[GOOD] (define-fun s116 () Bool (= s114 s115))
+[GOOD] (define-fun s117 () Bool (<= s103 s2))
+[GOOD] (define-fun s118 () Bool (or s116 s117))
+[GOOD] (define-fun s119 () Bool (<= s113 s112))
+[GOOD] (define-fun s120 () Int (ite s119 s112 s113))
+[GOOD] (define-fun s121 () Int (ite s104 s112 s120))
+[GOOD] (define-fun s122 () Int (ite s92 s100 s121))
+[GOOD] (define-fun s123 () Int (ite s80 s88 s122))
+[GOOD] (define-fun s124 () Int (ite s68 s76 s123))
+[GOOD] (define-fun s125 () Int (ite s56 s64 s124))
+[GOOD] (define-fun s126 () Int (ite s44 s52 s125))
+[GOOD] (define-fun s127 () Int (ite s32 s40 s126))
+[GOOD] (define-fun s128 () Int (ite s20 s28 s127))
+[GOOD] (define-fun s129 () Int (ite s8 s16 s128))
+[GOOD] (define-fun s130 () Int (ite s3 s2 s129))
+[GOOD] (define-fun s132 () Bool (> s130 s131))
+[GOOD] (define-fun s133 () Bool (not s132))
+[GOOD] (define-fun s134 () Bool (< s9 s2))
+[GOOD] (define-fun s135 () Bool (> s9 s131))
+[GOOD] (define-fun s136 () Bool (or s134 s135))
+[GOOD] (define-fun s137 () Bool (< s21 s2))
+[GOOD] (define-fun s138 () Bool (> s21 s131))
+[GOOD] (define-fun s139 () Bool (or s137 s138))
+[GOOD] (define-fun s140 () Bool (or s136 s139))
+[GOOD] (define-fun s141 () Bool (< s33 s2))
+[GOOD] (define-fun s142 () Bool (> s33 s131))
+[GOOD] (define-fun s143 () Bool (or s141 s142))
+[GOOD] (define-fun s144 () Bool (or s140 s143))
+[GOOD] (define-fun s145 () Bool (< s45 s2))
+[GOOD] (define-fun s146 () Bool (> s45 s131))
 [GOOD] (define-fun s147 () Bool (or s145 s146))
-[GOOD] (define-fun s148 () Bool (< s22 s3))
-[GOOD] (define-fun s149 () Bool (> s22 s142))
-[GOOD] (define-fun s150 () Bool (or s148 s149))
-[GOOD] (define-fun s151 () Bool (or s147 s150))
-[GOOD] (define-fun s152 () Bool (< s35 s3))
-[GOOD] (define-fun s153 () Bool (> s35 s142))
-[GOOD] (define-fun s154 () Bool (or s152 s153))
-[GOOD] (define-fun s155 () Bool (or s151 s154))
-[GOOD] (define-fun s156 () Bool (< s48 s3))
-[GOOD] (define-fun s157 () Bool (> s48 s142))
-[GOOD] (define-fun s158 () Bool (or s156 s157))
-[GOOD] (define-fun s159 () Bool (or s155 s158))
-[GOOD] (define-fun s160 () Bool (< s61 s3))
-[GOOD] (define-fun s161 () Bool (> s61 s142))
-[GOOD] (define-fun s162 () Bool (or s160 s161))
-[GOOD] (define-fun s163 () Bool (or s159 s162))
-[GOOD] (define-fun s164 () Bool (< s74 s3))
-[GOOD] (define-fun s165 () Bool (> s74 s142))
-[GOOD] (define-fun s166 () Bool (or s164 s165))
-[GOOD] (define-fun s167 () Bool (or s163 s166))
-[GOOD] (define-fun s168 () Bool (< s87 s3))
-[GOOD] (define-fun s169 () Bool (> s87 s142))
-[GOOD] (define-fun s170 () Bool (or s168 s169))
-[GOOD] (define-fun s171 () Bool (or s167 s170))
-[GOOD] (define-fun s172 () Bool (< s100 s3))
-[GOOD] (define-fun s173 () Bool (> s100 s142))
-[GOOD] (define-fun s174 () Bool (or s172 s173))
-[GOOD] (define-fun s175 () Bool (or s171 s174))
-[GOOD] (define-fun s176 () Bool (< s113 s3))
-[GOOD] (define-fun s177 () Bool (> s113 s142))
-[GOOD] (define-fun s178 () Bool (or s176 s177))
-[GOOD] (define-fun s179 () Bool (or s175 s178))
-[GOOD] (define-fun s180 () Bool (< s122 s3))
-[GOOD] (define-fun s181 () Bool (> s122 s142))
-[GOOD] (define-fun s182 () Bool (or s180 s181))
-[GOOD] (define-fun s183 () Bool (or s179 s182))
-[GOOD] (define-fun s184 () Bool (ite s112 s179 s183))
-[GOOD] (define-fun s185 () Bool (ite s99 s175 s184))
-[GOOD] (define-fun s186 () Bool (ite s86 s171 s185))
-[GOOD] (define-fun s187 () Bool (ite s73 s167 s186))
-[GOOD] (define-fun s188 () Bool (ite s60 s163 s187))
-[GOOD] (define-fun s189 () Bool (ite s47 s159 s188))
-[GOOD] (define-fun s190 () Bool (ite s34 s155 s189))
-[GOOD] (define-fun s191 () Bool (ite s21 s151 s190))
-[GOOD] (define-fun s192 () Bool (ite s8 s147 s191))
-[GOOD] (define-fun s193 () Bool (not s2))
-[GOOD] (define-fun s194 () Bool (and s192 s193))
-[GOOD] (define-fun s195 () Bool (or s144 s194))
-[GOOD] (assert s15)
-[GOOD] (assert s28)
-[GOOD] (assert s41)
-[GOOD] (assert s54)
-[GOOD] (assert s67)
-[GOOD] (assert s80)
-[GOOD] (assert s93)
-[GOOD] (assert s106)
-[GOOD] (assert s119)
-[GOOD] (assert s129)
-[GOOD] (assert s195)
+[GOOD] (define-fun s148 () Bool (or s144 s147))
+[GOOD] (define-fun s149 () Bool (< s57 s2))
+[GOOD] (define-fun s150 () Bool (> s57 s131))
+[GOOD] (define-fun s151 () Bool (or s149 s150))
+[GOOD] (define-fun s152 () Bool (or s148 s151))
+[GOOD] (define-fun s153 () Bool (< s69 s2))
+[GOOD] (define-fun s154 () Bool (> s69 s131))
+[GOOD] (define-fun s155 () Bool (or s153 s154))
+[GOOD] (define-fun s156 () Bool (or s152 s155))
+[GOOD] (define-fun s157 () Bool (< s81 s2))
+[GOOD] (define-fun s158 () Bool (> s81 s131))
+[GOOD] (define-fun s159 () Bool (or s157 s158))
+[GOOD] (define-fun s160 () Bool (or s156 s159))
+[GOOD] (define-fun s161 () Bool (< s93 s2))
+[GOOD] (define-fun s162 () Bool (> s93 s131))
+[GOOD] (define-fun s163 () Bool (or s161 s162))
+[GOOD] (define-fun s164 () Bool (or s160 s163))
+[GOOD] (define-fun s165 () Bool (< s105 s2))
+[GOOD] (define-fun s166 () Bool (> s105 s131))
+[GOOD] (define-fun s167 () Bool (or s165 s166))
+[GOOD] (define-fun s168 () Bool (or s164 s167))
+[GOOD] (define-fun s169 () Bool (< s113 s2))
+[GOOD] (define-fun s170 () Bool (> s113 s131))
+[GOOD] (define-fun s171 () Bool (or s169 s170))
+[GOOD] (define-fun s172 () Bool (or s168 s171))
+[GOOD] (define-fun s173 () Bool (ite s104 s168 s172))
+[GOOD] (define-fun s174 () Bool (ite s92 s164 s173))
+[GOOD] (define-fun s175 () Bool (ite s80 s160 s174))
+[GOOD] (define-fun s176 () Bool (ite s68 s156 s175))
+[GOOD] (define-fun s177 () Bool (ite s56 s152 s176))
+[GOOD] (define-fun s178 () Bool (ite s44 s148 s177))
+[GOOD] (define-fun s179 () Bool (ite s32 s144 s178))
+[GOOD] (define-fun s180 () Bool (ite s20 s140 s179))
+[GOOD] (define-fun s181 () Bool (ite s8 s136 s180))
+[GOOD] (define-fun s182 () Bool (not s3))
+[GOOD] (define-fun s183 () Bool (and s181 s182))
+[GOOD] (define-fun s184 () Bool (or s133 s183))
+[GOOD] (assert s14)
+[GOOD] (assert s26)
+[GOOD] (assert s38)
+[GOOD] (assert s50)
+[GOOD] (assert s62)
+[GOOD] (assert s74)
+[GOOD] (assert s86)
+[GOOD] (assert s98)
+[GOOD] (assert s110)
+[GOOD] (assert s118)
+[GOOD] (assert s184)
 [SEND] (check-sat)
 [RECV] sat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/maxrWithFailure.gold b/SBVTestSuite/GoldFiles/maxrWithFailure.gold
--- a/SBVTestSuite/GoldFiles/maxrWithFailure.gold
+++ b/SBVTestSuite/GoldFiles/maxrWithFailure.gold
@@ -10,230 +10,220 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s3 () Int 0)
-[GOOD] (define-fun s9 () Int 1)
-[GOOD] (define-fun s142 () Int 10)
-[GOOD] (define-fun s1 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s6 () Int 1)
+[GOOD] (define-fun s131 () Int 10)
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "ints"
 [GOOD] (declare-fun s4 () Int) ; tracks user variable "__internal_sbv_s4"
-[GOOD] (declare-fun s16 () Int) ; tracks user variable "__internal_sbv_s16"
-[GOOD] (declare-fun s27 () Int) ; tracks user variable "__internal_sbv_s27"
-[GOOD] (declare-fun s38 () Int) ; tracks user variable "__internal_sbv_s38"
-[GOOD] (declare-fun s49 () Int) ; tracks user variable "__internal_sbv_s49"
-[GOOD] (declare-fun s60 () Int) ; tracks user variable "__internal_sbv_s60"
-[GOOD] (declare-fun s71 () Int) ; tracks user variable "__internal_sbv_s71"
-[GOOD] (declare-fun s82 () Int) ; tracks user variable "__internal_sbv_s82"
-[GOOD] (declare-fun s93 () Int) ; tracks user variable "__internal_sbv_s93"
-[GOOD] (declare-fun s104 () Int) ; tracks user variable "__internal_sbv_s104"
+[GOOD] (declare-fun s15 () Int) ; tracks user variable "__internal_sbv_s15"
+[GOOD] (declare-fun s25 () Int) ; tracks user variable "__internal_sbv_s25"
+[GOOD] (declare-fun s35 () Int) ; tracks user variable "__internal_sbv_s35"
+[GOOD] (declare-fun s45 () Int) ; tracks user variable "__internal_sbv_s45"
+[GOOD] (declare-fun s55 () Int) ; tracks user variable "__internal_sbv_s55"
+[GOOD] (declare-fun s65 () Int) ; tracks user variable "__internal_sbv_s65"
+[GOOD] (declare-fun s75 () Int) ; tracks user variable "__internal_sbv_s75"
+[GOOD] (declare-fun s85 () Int) ; tracks user variable "__internal_sbv_s85"
+[GOOD] (declare-fun s95 () Int) ; tracks user variable "__internal_sbv_s95"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user given axioms ---
 [GOOD] ; --- formula ---
-[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s1 () Int (seq.len s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
 [GOOD] (define-fun s5 () (Seq Int) (seq.unit s4))
-[GOOD] (define-fun s6 () Int (seq.len s0))
-[GOOD] (define-fun s7 () Bool (> s6 s3))
-[GOOD] (define-fun s8 () Bool (not s7))
-[GOOD] (define-fun s10 () (Seq Int) (seq.extract s0 s3 s9))
-[GOOD] (define-fun s11 () Bool (= s5 s10))
-[GOOD] (define-fun s12 () Bool (or s8 s11))
-[GOOD] (define-fun s13 () Int (- s6 s9))
-[GOOD] (define-fun s14 () (Seq Int) (seq.extract s0 s9 s13))
-[GOOD] (define-fun s15 () Bool (= s1 s14))
-[GOOD] (define-fun s17 () (Seq Int) (seq.unit s16))
-[GOOD] (define-fun s18 () Int (seq.len s14))
-[GOOD] (define-fun s19 () Bool (> s18 s3))
-[GOOD] (define-fun s20 () Bool (not s19))
-[GOOD] (define-fun s21 () (Seq Int) (seq.extract s14 s3 s9))
-[GOOD] (define-fun s22 () Bool (= s17 s21))
-[GOOD] (define-fun s23 () Bool (or s20 s22))
-[GOOD] (define-fun s24 () Int (- s18 s9))
-[GOOD] (define-fun s25 () (Seq Int) (seq.extract s14 s9 s24))
-[GOOD] (define-fun s26 () Bool (= s1 s25))
-[GOOD] (define-fun s28 () (Seq Int) (seq.unit s27))
-[GOOD] (define-fun s29 () Int (seq.len s25))
-[GOOD] (define-fun s30 () Bool (> s29 s3))
-[GOOD] (define-fun s31 () Bool (not s30))
-[GOOD] (define-fun s32 () (Seq Int) (seq.extract s25 s3 s9))
-[GOOD] (define-fun s33 () Bool (= s28 s32))
-[GOOD] (define-fun s34 () Bool (or s31 s33))
-[GOOD] (define-fun s35 () Int (- s29 s9))
-[GOOD] (define-fun s36 () (Seq Int) (seq.extract s25 s9 s35))
-[GOOD] (define-fun s37 () Bool (= s1 s36))
-[GOOD] (define-fun s39 () (Seq Int) (seq.unit s38))
-[GOOD] (define-fun s40 () Int (seq.len s36))
-[GOOD] (define-fun s41 () Bool (> s40 s3))
-[GOOD] (define-fun s42 () Bool (not s41))
-[GOOD] (define-fun s43 () (Seq Int) (seq.extract s36 s3 s9))
-[GOOD] (define-fun s44 () Bool (= s39 s43))
-[GOOD] (define-fun s45 () Bool (or s42 s44))
-[GOOD] (define-fun s46 () Int (- s40 s9))
-[GOOD] (define-fun s47 () (Seq Int) (seq.extract s36 s9 s46))
-[GOOD] (define-fun s48 () Bool (= s1 s47))
-[GOOD] (define-fun s50 () (Seq Int) (seq.unit s49))
-[GOOD] (define-fun s51 () Int (seq.len s47))
-[GOOD] (define-fun s52 () Bool (> s51 s3))
-[GOOD] (define-fun s53 () Bool (not s52))
-[GOOD] (define-fun s54 () (Seq Int) (seq.extract s47 s3 s9))
-[GOOD] (define-fun s55 () Bool (= s50 s54))
-[GOOD] (define-fun s56 () Bool (or s53 s55))
-[GOOD] (define-fun s57 () Int (- s51 s9))
-[GOOD] (define-fun s58 () (Seq Int) (seq.extract s47 s9 s57))
-[GOOD] (define-fun s59 () Bool (= s1 s58))
-[GOOD] (define-fun s61 () (Seq Int) (seq.unit s60))
-[GOOD] (define-fun s62 () Int (seq.len s58))
-[GOOD] (define-fun s63 () Bool (> s62 s3))
-[GOOD] (define-fun s64 () Bool (not s63))
-[GOOD] (define-fun s65 () (Seq Int) (seq.extract s58 s3 s9))
-[GOOD] (define-fun s66 () Bool (= s61 s65))
-[GOOD] (define-fun s67 () Bool (or s64 s66))
-[GOOD] (define-fun s68 () Int (- s62 s9))
-[GOOD] (define-fun s69 () (Seq Int) (seq.extract s58 s9 s68))
-[GOOD] (define-fun s70 () Bool (= s1 s69))
-[GOOD] (define-fun s72 () (Seq Int) (seq.unit s71))
-[GOOD] (define-fun s73 () Int (seq.len s69))
-[GOOD] (define-fun s74 () Bool (> s73 s3))
-[GOOD] (define-fun s75 () Bool (not s74))
-[GOOD] (define-fun s76 () (Seq Int) (seq.extract s69 s3 s9))
-[GOOD] (define-fun s77 () Bool (= s72 s76))
-[GOOD] (define-fun s78 () Bool (or s75 s77))
-[GOOD] (define-fun s79 () Int (- s73 s9))
-[GOOD] (define-fun s80 () (Seq Int) (seq.extract s69 s9 s79))
-[GOOD] (define-fun s81 () Bool (= s1 s80))
-[GOOD] (define-fun s83 () (Seq Int) (seq.unit s82))
-[GOOD] (define-fun s84 () Int (seq.len s80))
-[GOOD] (define-fun s85 () Bool (> s84 s3))
-[GOOD] (define-fun s86 () Bool (not s85))
-[GOOD] (define-fun s87 () (Seq Int) (seq.extract s80 s3 s9))
-[GOOD] (define-fun s88 () Bool (= s83 s87))
-[GOOD] (define-fun s89 () Bool (or s86 s88))
-[GOOD] (define-fun s90 () Int (- s84 s9))
-[GOOD] (define-fun s91 () (Seq Int) (seq.extract s80 s9 s90))
-[GOOD] (define-fun s92 () Bool (= s1 s91))
-[GOOD] (define-fun s94 () (Seq Int) (seq.unit s93))
-[GOOD] (define-fun s95 () Int (seq.len s91))
-[GOOD] (define-fun s96 () Bool (> s95 s3))
-[GOOD] (define-fun s97 () Bool (not s96))
-[GOOD] (define-fun s98 () (Seq Int) (seq.extract s91 s3 s9))
-[GOOD] (define-fun s99 () Bool (= s94 s98))
-[GOOD] (define-fun s100 () Bool (or s97 s99))
-[GOOD] (define-fun s101 () Int (- s95 s9))
-[GOOD] (define-fun s102 () (Seq Int) (seq.extract s91 s9 s101))
-[GOOD] (define-fun s103 () Bool (= s1 s102))
-[GOOD] (define-fun s105 () (Seq Int) (seq.unit s104))
-[GOOD] (define-fun s106 () Int (seq.len s102))
-[GOOD] (define-fun s107 () Bool (> s106 s3))
-[GOOD] (define-fun s108 () Bool (not s107))
-[GOOD] (define-fun s109 () (Seq Int) (seq.extract s102 s3 s9))
-[GOOD] (define-fun s110 () Bool (= s105 s109))
-[GOOD] (define-fun s111 () Bool (or s108 s110))
-[GOOD] (define-fun s112 () Bool (<= s104 s3))
-[GOOD] (define-fun s113 () Int (ite s112 s3 s104))
-[GOOD] (define-fun s114 () Int (ite s103 s3 s113))
-[GOOD] (define-fun s115 () Bool (<= s93 s114))
-[GOOD] (define-fun s116 () Int (ite s115 s114 s93))
-[GOOD] (define-fun s117 () Int (ite s92 s3 s116))
-[GOOD] (define-fun s118 () Bool (<= s82 s117))
-[GOOD] (define-fun s119 () Int (ite s118 s117 s82))
-[GOOD] (define-fun s120 () Int (ite s81 s3 s119))
-[GOOD] (define-fun s121 () Bool (<= s71 s120))
-[GOOD] (define-fun s122 () Int (ite s121 s120 s71))
-[GOOD] (define-fun s123 () Int (ite s70 s3 s122))
-[GOOD] (define-fun s124 () Bool (<= s60 s123))
-[GOOD] (define-fun s125 () Int (ite s124 s123 s60))
-[GOOD] (define-fun s126 () Int (ite s59 s3 s125))
-[GOOD] (define-fun s127 () Bool (<= s49 s126))
-[GOOD] (define-fun s128 () Int (ite s127 s126 s49))
-[GOOD] (define-fun s129 () Int (ite s48 s3 s128))
-[GOOD] (define-fun s130 () Bool (<= s38 s129))
-[GOOD] (define-fun s131 () Int (ite s130 s129 s38))
-[GOOD] (define-fun s132 () Int (ite s37 s3 s131))
-[GOOD] (define-fun s133 () Bool (<= s27 s132))
-[GOOD] (define-fun s134 () Int (ite s133 s132 s27))
-[GOOD] (define-fun s135 () Int (ite s26 s3 s134))
-[GOOD] (define-fun s136 () Bool (<= s16 s135))
-[GOOD] (define-fun s137 () Int (ite s136 s135 s16))
-[GOOD] (define-fun s138 () Int (ite s15 s3 s137))
-[GOOD] (define-fun s139 () Bool (<= s4 s138))
-[GOOD] (define-fun s140 () Int (ite s139 s138 s4))
-[GOOD] (define-fun s141 () Int (ite s2 s3 s140))
-[GOOD] (define-fun s143 () Bool (> s141 s142))
-[GOOD] (define-fun s144 () Bool (not s143))
-[GOOD] (define-fun s145 () Bool (< s104 s3))
-[GOOD] (define-fun s146 () Bool (> s104 s142))
+[GOOD] (define-fun s7 () (Seq Int) (seq.extract s0 s2 s6))
+[GOOD] (define-fun s8 () Bool (= s5 s7))
+[GOOD] (define-fun s9 () Bool (<= s1 s2))
+[GOOD] (define-fun s10 () Bool (or s8 s9))
+[GOOD] (define-fun s11 () Int (- s1 s6))
+[GOOD] (define-fun s12 () (Seq Int) (seq.extract s0 s6 s11))
+[GOOD] (define-fun s13 () Int (seq.len s12))
+[GOOD] (define-fun s14 () Bool (= s2 s13))
+[GOOD] (define-fun s16 () (Seq Int) (seq.unit s15))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s12 s2 s6))
+[GOOD] (define-fun s18 () Bool (= s16 s17))
+[GOOD] (define-fun s19 () Bool (<= s13 s2))
+[GOOD] (define-fun s20 () Bool (or s18 s19))
+[GOOD] (define-fun s21 () Int (- s13 s6))
+[GOOD] (define-fun s22 () (Seq Int) (seq.extract s12 s6 s21))
+[GOOD] (define-fun s23 () Int (seq.len s22))
+[GOOD] (define-fun s24 () Bool (= s2 s23))
+[GOOD] (define-fun s26 () (Seq Int) (seq.unit s25))
+[GOOD] (define-fun s27 () (Seq Int) (seq.extract s22 s2 s6))
+[GOOD] (define-fun s28 () Bool (= s26 s27))
+[GOOD] (define-fun s29 () Bool (<= s23 s2))
+[GOOD] (define-fun s30 () Bool (or s28 s29))
+[GOOD] (define-fun s31 () Int (- s23 s6))
+[GOOD] (define-fun s32 () (Seq Int) (seq.extract s22 s6 s31))
+[GOOD] (define-fun s33 () Int (seq.len s32))
+[GOOD] (define-fun s34 () Bool (= s2 s33))
+[GOOD] (define-fun s36 () (Seq Int) (seq.unit s35))
+[GOOD] (define-fun s37 () (Seq Int) (seq.extract s32 s2 s6))
+[GOOD] (define-fun s38 () Bool (= s36 s37))
+[GOOD] (define-fun s39 () Bool (<= s33 s2))
+[GOOD] (define-fun s40 () Bool (or s38 s39))
+[GOOD] (define-fun s41 () Int (- s33 s6))
+[GOOD] (define-fun s42 () (Seq Int) (seq.extract s32 s6 s41))
+[GOOD] (define-fun s43 () Int (seq.len s42))
+[GOOD] (define-fun s44 () Bool (= s2 s43))
+[GOOD] (define-fun s46 () (Seq Int) (seq.unit s45))
+[GOOD] (define-fun s47 () (Seq Int) (seq.extract s42 s2 s6))
+[GOOD] (define-fun s48 () Bool (= s46 s47))
+[GOOD] (define-fun s49 () Bool (<= s43 s2))
+[GOOD] (define-fun s50 () Bool (or s48 s49))
+[GOOD] (define-fun s51 () Int (- s43 s6))
+[GOOD] (define-fun s52 () (Seq Int) (seq.extract s42 s6 s51))
+[GOOD] (define-fun s53 () Int (seq.len s52))
+[GOOD] (define-fun s54 () Bool (= s2 s53))
+[GOOD] (define-fun s56 () (Seq Int) (seq.unit s55))
+[GOOD] (define-fun s57 () (Seq Int) (seq.extract s52 s2 s6))
+[GOOD] (define-fun s58 () Bool (= s56 s57))
+[GOOD] (define-fun s59 () Bool (<= s53 s2))
+[GOOD] (define-fun s60 () Bool (or s58 s59))
+[GOOD] (define-fun s61 () Int (- s53 s6))
+[GOOD] (define-fun s62 () (Seq Int) (seq.extract s52 s6 s61))
+[GOOD] (define-fun s63 () Int (seq.len s62))
+[GOOD] (define-fun s64 () Bool (= s2 s63))
+[GOOD] (define-fun s66 () (Seq Int) (seq.unit s65))
+[GOOD] (define-fun s67 () (Seq Int) (seq.extract s62 s2 s6))
+[GOOD] (define-fun s68 () Bool (= s66 s67))
+[GOOD] (define-fun s69 () Bool (<= s63 s2))
+[GOOD] (define-fun s70 () Bool (or s68 s69))
+[GOOD] (define-fun s71 () Int (- s63 s6))
+[GOOD] (define-fun s72 () (Seq Int) (seq.extract s62 s6 s71))
+[GOOD] (define-fun s73 () Int (seq.len s72))
+[GOOD] (define-fun s74 () Bool (= s2 s73))
+[GOOD] (define-fun s76 () (Seq Int) (seq.unit s75))
+[GOOD] (define-fun s77 () (Seq Int) (seq.extract s72 s2 s6))
+[GOOD] (define-fun s78 () Bool (= s76 s77))
+[GOOD] (define-fun s79 () Bool (<= s73 s2))
+[GOOD] (define-fun s80 () Bool (or s78 s79))
+[GOOD] (define-fun s81 () Int (- s73 s6))
+[GOOD] (define-fun s82 () (Seq Int) (seq.extract s72 s6 s81))
+[GOOD] (define-fun s83 () Int (seq.len s82))
+[GOOD] (define-fun s84 () Bool (= s2 s83))
+[GOOD] (define-fun s86 () (Seq Int) (seq.unit s85))
+[GOOD] (define-fun s87 () (Seq Int) (seq.extract s82 s2 s6))
+[GOOD] (define-fun s88 () Bool (= s86 s87))
+[GOOD] (define-fun s89 () Bool (<= s83 s2))
+[GOOD] (define-fun s90 () Bool (or s88 s89))
+[GOOD] (define-fun s91 () Int (- s83 s6))
+[GOOD] (define-fun s92 () (Seq Int) (seq.extract s82 s6 s91))
+[GOOD] (define-fun s93 () Int (seq.len s92))
+[GOOD] (define-fun s94 () Bool (= s2 s93))
+[GOOD] (define-fun s96 () (Seq Int) (seq.unit s95))
+[GOOD] (define-fun s97 () (Seq Int) (seq.extract s92 s2 s6))
+[GOOD] (define-fun s98 () Bool (= s96 s97))
+[GOOD] (define-fun s99 () Bool (<= s93 s2))
+[GOOD] (define-fun s100 () Bool (or s98 s99))
+[GOOD] (define-fun s101 () Bool (<= s95 s2))
+[GOOD] (define-fun s102 () Int (ite s101 s2 s95))
+[GOOD] (define-fun s103 () Int (ite s94 s2 s102))
+[GOOD] (define-fun s104 () Bool (<= s85 s103))
+[GOOD] (define-fun s105 () Int (ite s104 s103 s85))
+[GOOD] (define-fun s106 () Int (ite s84 s2 s105))
+[GOOD] (define-fun s107 () Bool (<= s75 s106))
+[GOOD] (define-fun s108 () Int (ite s107 s106 s75))
+[GOOD] (define-fun s109 () Int (ite s74 s2 s108))
+[GOOD] (define-fun s110 () Bool (<= s65 s109))
+[GOOD] (define-fun s111 () Int (ite s110 s109 s65))
+[GOOD] (define-fun s112 () Int (ite s64 s2 s111))
+[GOOD] (define-fun s113 () Bool (<= s55 s112))
+[GOOD] (define-fun s114 () Int (ite s113 s112 s55))
+[GOOD] (define-fun s115 () Int (ite s54 s2 s114))
+[GOOD] (define-fun s116 () Bool (<= s45 s115))
+[GOOD] (define-fun s117 () Int (ite s116 s115 s45))
+[GOOD] (define-fun s118 () Int (ite s44 s2 s117))
+[GOOD] (define-fun s119 () Bool (<= s35 s118))
+[GOOD] (define-fun s120 () Int (ite s119 s118 s35))
+[GOOD] (define-fun s121 () Int (ite s34 s2 s120))
+[GOOD] (define-fun s122 () Bool (<= s25 s121))
+[GOOD] (define-fun s123 () Int (ite s122 s121 s25))
+[GOOD] (define-fun s124 () Int (ite s24 s2 s123))
+[GOOD] (define-fun s125 () Bool (<= s15 s124))
+[GOOD] (define-fun s126 () Int (ite s125 s124 s15))
+[GOOD] (define-fun s127 () Int (ite s14 s2 s126))
+[GOOD] (define-fun s128 () Bool (<= s4 s127))
+[GOOD] (define-fun s129 () Int (ite s128 s127 s4))
+[GOOD] (define-fun s130 () Int (ite s3 s2 s129))
+[GOOD] (define-fun s132 () Bool (> s130 s131))
+[GOOD] (define-fun s133 () Bool (not s132))
+[GOOD] (define-fun s134 () Bool (< s95 s2))
+[GOOD] (define-fun s135 () Bool (> s95 s131))
+[GOOD] (define-fun s136 () Bool (or s134 s135))
+[GOOD] (define-fun s137 () Bool (not s94))
+[GOOD] (define-fun s138 () Bool (and s136 s137))
+[GOOD] (define-fun s139 () Bool (< s85 s2))
+[GOOD] (define-fun s140 () Bool (> s85 s131))
+[GOOD] (define-fun s141 () Bool (or s139 s140))
+[GOOD] (define-fun s142 () Bool (or s138 s141))
+[GOOD] (define-fun s143 () Bool (not s84))
+[GOOD] (define-fun s144 () Bool (and s142 s143))
+[GOOD] (define-fun s145 () Bool (< s75 s2))
+[GOOD] (define-fun s146 () Bool (> s75 s131))
 [GOOD] (define-fun s147 () Bool (or s145 s146))
-[GOOD] (define-fun s148 () Bool (not s103))
-[GOOD] (define-fun s149 () Bool (and s147 s148))
-[GOOD] (define-fun s150 () Bool (< s93 s3))
-[GOOD] (define-fun s151 () Bool (> s93 s142))
-[GOOD] (define-fun s152 () Bool (or s150 s151))
-[GOOD] (define-fun s153 () Bool (or s149 s152))
-[GOOD] (define-fun s154 () Bool (not s92))
-[GOOD] (define-fun s155 () Bool (and s153 s154))
-[GOOD] (define-fun s156 () Bool (< s82 s3))
-[GOOD] (define-fun s157 () Bool (> s82 s142))
-[GOOD] (define-fun s158 () Bool (or s156 s157))
-[GOOD] (define-fun s159 () Bool (or s155 s158))
-[GOOD] (define-fun s160 () Bool (not s81))
-[GOOD] (define-fun s161 () Bool (and s159 s160))
-[GOOD] (define-fun s162 () Bool (< s71 s3))
-[GOOD] (define-fun s163 () Bool (> s71 s142))
-[GOOD] (define-fun s164 () Bool (or s162 s163))
-[GOOD] (define-fun s165 () Bool (or s161 s164))
-[GOOD] (define-fun s166 () Bool (not s70))
-[GOOD] (define-fun s167 () Bool (and s165 s166))
-[GOOD] (define-fun s168 () Bool (< s60 s3))
-[GOOD] (define-fun s169 () Bool (> s60 s142))
-[GOOD] (define-fun s170 () Bool (or s168 s169))
-[GOOD] (define-fun s171 () Bool (or s167 s170))
-[GOOD] (define-fun s172 () Bool (not s59))
-[GOOD] (define-fun s173 () Bool (and s171 s172))
-[GOOD] (define-fun s174 () Bool (< s49 s3))
-[GOOD] (define-fun s175 () Bool (> s49 s142))
-[GOOD] (define-fun s176 () Bool (or s174 s175))
-[GOOD] (define-fun s177 () Bool (or s173 s176))
-[GOOD] (define-fun s178 () Bool (not s48))
-[GOOD] (define-fun s179 () Bool (and s177 s178))
-[GOOD] (define-fun s180 () Bool (< s38 s3))
-[GOOD] (define-fun s181 () Bool (> s38 s142))
-[GOOD] (define-fun s182 () Bool (or s180 s181))
-[GOOD] (define-fun s183 () Bool (or s179 s182))
-[GOOD] (define-fun s184 () Bool (not s37))
-[GOOD] (define-fun s185 () Bool (and s183 s184))
-[GOOD] (define-fun s186 () Bool (< s27 s3))
-[GOOD] (define-fun s187 () Bool (> s27 s142))
-[GOOD] (define-fun s188 () Bool (or s186 s187))
-[GOOD] (define-fun s189 () Bool (or s185 s188))
-[GOOD] (define-fun s190 () Bool (not s26))
-[GOOD] (define-fun s191 () Bool (and s189 s190))
-[GOOD] (define-fun s192 () Bool (< s16 s3))
-[GOOD] (define-fun s193 () Bool (> s16 s142))
-[GOOD] (define-fun s194 () Bool (or s192 s193))
-[GOOD] (define-fun s195 () Bool (or s191 s194))
-[GOOD] (define-fun s196 () Bool (not s15))
-[GOOD] (define-fun s197 () Bool (and s195 s196))
-[GOOD] (define-fun s198 () Bool (< s4 s3))
-[GOOD] (define-fun s199 () Bool (> s4 s142))
-[GOOD] (define-fun s200 () Bool (or s198 s199))
-[GOOD] (define-fun s201 () Bool (or s197 s200))
-[GOOD] (define-fun s202 () Bool (not s2))
-[GOOD] (define-fun s203 () Bool (and s201 s202))
-[GOOD] (define-fun s204 () Bool (or s144 s203))
-[GOOD] (assert s12)
-[GOOD] (assert s23)
-[GOOD] (assert s34)
-[GOOD] (assert s45)
-[GOOD] (assert s56)
-[GOOD] (assert s67)
-[GOOD] (assert s78)
-[GOOD] (assert s89)
+[GOOD] (define-fun s148 () Bool (or s144 s147))
+[GOOD] (define-fun s149 () Bool (not s74))
+[GOOD] (define-fun s150 () Bool (and s148 s149))
+[GOOD] (define-fun s151 () Bool (< s65 s2))
+[GOOD] (define-fun s152 () Bool (> s65 s131))
+[GOOD] (define-fun s153 () Bool (or s151 s152))
+[GOOD] (define-fun s154 () Bool (or s150 s153))
+[GOOD] (define-fun s155 () Bool (not s64))
+[GOOD] (define-fun s156 () Bool (and s154 s155))
+[GOOD] (define-fun s157 () Bool (< s55 s2))
+[GOOD] (define-fun s158 () Bool (> s55 s131))
+[GOOD] (define-fun s159 () Bool (or s157 s158))
+[GOOD] (define-fun s160 () Bool (or s156 s159))
+[GOOD] (define-fun s161 () Bool (not s54))
+[GOOD] (define-fun s162 () Bool (and s160 s161))
+[GOOD] (define-fun s163 () Bool (< s45 s2))
+[GOOD] (define-fun s164 () Bool (> s45 s131))
+[GOOD] (define-fun s165 () Bool (or s163 s164))
+[GOOD] (define-fun s166 () Bool (or s162 s165))
+[GOOD] (define-fun s167 () Bool (not s44))
+[GOOD] (define-fun s168 () Bool (and s166 s167))
+[GOOD] (define-fun s169 () Bool (< s35 s2))
+[GOOD] (define-fun s170 () Bool (> s35 s131))
+[GOOD] (define-fun s171 () Bool (or s169 s170))
+[GOOD] (define-fun s172 () Bool (or s168 s171))
+[GOOD] (define-fun s173 () Bool (not s34))
+[GOOD] (define-fun s174 () Bool (and s172 s173))
+[GOOD] (define-fun s175 () Bool (< s25 s2))
+[GOOD] (define-fun s176 () Bool (> s25 s131))
+[GOOD] (define-fun s177 () Bool (or s175 s176))
+[GOOD] (define-fun s178 () Bool (or s174 s177))
+[GOOD] (define-fun s179 () Bool (not s24))
+[GOOD] (define-fun s180 () Bool (and s178 s179))
+[GOOD] (define-fun s181 () Bool (< s15 s2))
+[GOOD] (define-fun s182 () Bool (> s15 s131))
+[GOOD] (define-fun s183 () Bool (or s181 s182))
+[GOOD] (define-fun s184 () Bool (or s180 s183))
+[GOOD] (define-fun s185 () Bool (not s14))
+[GOOD] (define-fun s186 () Bool (and s184 s185))
+[GOOD] (define-fun s187 () Bool (< s4 s2))
+[GOOD] (define-fun s188 () Bool (> s4 s131))
+[GOOD] (define-fun s189 () Bool (or s187 s188))
+[GOOD] (define-fun s190 () Bool (or s186 s189))
+[GOOD] (define-fun s191 () Bool (not s3))
+[GOOD] (define-fun s192 () Bool (and s190 s191))
+[GOOD] (define-fun s193 () Bool (or s133 s192))
+[GOOD] (assert s10)
+[GOOD] (assert s20)
+[GOOD] (assert s30)
+[GOOD] (assert s40)
+[GOOD] (assert s50)
+[GOOD] (assert s60)
+[GOOD] (assert s70)
+[GOOD] (assert s80)
+[GOOD] (assert s90)
 [GOOD] (assert s100)
-[GOOD] (assert s111)
-[GOOD] (assert s204)
+[GOOD] (assert s193)
 [SEND] (check-sat)
 [RECV] sat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/noOpt1.gold b/SBVTestSuite/GoldFiles/noOpt1.gold
--- a/SBVTestSuite/GoldFiles/noOpt1.gold
+++ b/SBVTestSuite/GoldFiles/noOpt1.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8))
diff --git a/SBVTestSuite/GoldFiles/noOpt2.gold b/SBVTestSuite/GoldFiles/noOpt2.gold
--- a/SBVTestSuite/GoldFiles/noOpt2.gold
+++ b/SBVTestSuite/GoldFiles/noOpt2.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8))
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_max.gold
--- a/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_max.gold
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_max.gold
@@ -1,3 +1,3 @@
 Optimal model:
   x = 127 :: Int8
-  m = 127 :: Int8
+  m = 255 :: Word8
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_min.gold
--- a/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_min.gold
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_08_signed_min.gold
@@ -1,3 +1,3 @@
 Optimal model:
   x = -128 :: Int8
-  m = -128 :: Int8
+  m =    0 :: Word8
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_max.gold
--- a/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_max.gold
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_max.gold
@@ -1,3 +1,3 @@
 Optimal model:
   x = 32767 :: Int16
-  m = 32767 :: Int16
+  m = 65535 :: Word16
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_min.gold
--- a/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_min.gold
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_16_signed_min.gold
@@ -1,3 +1,3 @@
 Optimal model:
   x = -32768 :: Int16
-  m = -32768 :: Int16
+  m =      0 :: Word16
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_max.gold
--- a/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_max.gold
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_max.gold
@@ -1,3 +1,3 @@
 Optimal model:
   x = 2147483647 :: Int32
-  m = 2147483647 :: Int32
+  m = 4294967295 :: Word32
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_min.gold
--- a/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_min.gold
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_32_signed_min.gold
@@ -1,3 +1,3 @@
 Optimal model:
   x = -2147483648 :: Int32
-  m = -2147483648 :: Int32
+  m =           0 :: Word32
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_max.gold b/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_max.gold
--- a/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_max.gold
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_max.gold
@@ -1,3 +1,3 @@
 Optimal model:
-  x = 9223372036854775807 :: Int64
-  m = 9223372036854775807 :: Int64
+  x =  9223372036854775807 :: Int64
+  m = 18446744073709551615 :: Word64
diff --git a/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_min.gold b/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_min.gold
--- a/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_min.gold
+++ b/SBVTestSuite/GoldFiles/optBasicsRange_64_signed_min.gold
@@ -1,3 +1,3 @@
 Optimal model:
   x = -9223372036854775808 :: Int64
-  m = -9223372036854775808 :: Int64
+  m =                    0 :: Word64
diff --git a/SBVTestSuite/GoldFiles/optFloat1.gold b/SBVTestSuite/GoldFiles/optFloat1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat1.gold
@@ -0,0 +1,108 @@
+Objective "min-x": Optimal model:
+  x     =          -3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 1 11111110 11111111111111111111111
+             Hex: FF7F FFFF
+       Precision: SP
+            Sign: Negative
+        Exponent: 127 (Stored: 254, Bias: 127)
+       Hex-float: -0x1.fffffep127
+           Value: -3.4028235e38 (NORMAL)
+  y     = 9.351032988705757e-251 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------F52-------------------------
+          Binary: 0 00011000000 0101011011001001110011000000001001101000111010000000
+             Hex: 0C05 6C9C C026 8E80
+       Precision: DP
+            Sign: Positive
+        Exponent: -831 (Stored: 192, Bias: 1023)
+       Hex-float: +0x1.56c9cc0268e8p-831
+           Value: +9.351032988705757e-251 (NORMAL)
+  min-x =             0x00800000 :: Word32
+  max-x =             0x00800000 :: Word32
+  min-y =     0x8c056c9cc0268e80 :: Word64
+  max-y =     0x8c056c9cc0268e80 :: Word64
+Objective "max-x": Optimal model:
+  x     =           3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 11111110 11111111111111111111111
+             Hex: 7F7F FFFF
+       Precision: SP
+            Sign: Positive
+        Exponent: 127 (Stored: 254, Bias: 127)
+       Hex-float: +0x1.fffffep127
+           Value: +3.4028235e38 (NORMAL)
+  y     = 9.351032988705757e-251 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------F52-------------------------
+          Binary: 0 00011000000 0101011011001001110011000000001001101000111010000000
+             Hex: 0C05 6C9C C026 8E80
+       Precision: DP
+            Sign: Positive
+        Exponent: -831 (Stored: 192, Bias: 1023)
+       Hex-float: +0x1.56c9cc0268e8p-831
+           Value: +9.351032988705757e-251 (NORMAL)
+  min-x =             0xff7fffff :: Word32
+  max-x =             0xff7fffff :: Word32
+  min-y =     0x8c056c9cc0268e80 :: Word64
+  max-y =     0x8c056c9cc0268e80 :: Word64
+Objective "min-y": Optimal model:
+  x     =            3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 11111110 11111111111111111111111
+             Hex: 7F7F FFFF
+       Precision: SP
+            Sign: Positive
+        Exponent: 127 (Stored: 254, Bias: 127)
+       Hex-float: +0x1.fffffep127
+           Value: +3.4028235e38 (NORMAL)
+  y     = -1.7976931348623157e308 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------F52-------------------------
+          Binary: 1 11111111110 1111111111111111111111111111111111111111111111111111
+             Hex: FFEF FFFF FFFF FFFF
+       Precision: DP
+            Sign: Negative
+        Exponent: 1023 (Stored: 2046, Bias: 1023)
+       Hex-float: -0x1.fffffffffffffp1023
+           Value: -1.7976931348623157e308 (NORMAL)
+  min-x =              0xff7fffff :: Word32
+  max-x =              0xff7fffff :: Word32
+  min-y =      0x0010000000000000 :: Word64
+  max-y =      0x0010000000000000 :: Word64
+Objective "max-y": Optimal model:
+  x     =          -1.8892078e22 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 1 11001001 00000000000010010001000
+             Hex: E480 0488
+       Precision: SP
+            Sign: Negative
+        Exponent: 74 (Stored: 201, Bias: 127)
+       Hex-float: -0x1.00091p74
+           Value: -1.8892078e22 (NORMAL)
+  y     = 1.7976931348623157e308 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------F52-------------------------
+          Binary: 0 11111111110 1111111111111111111111111111111111111111111111111111
+             Hex: 7FEF FFFF FFFF FFFF
+       Precision: DP
+            Sign: Positive
+        Exponent: 1023 (Stored: 2046, Bias: 1023)
+       Hex-float: +0x1.fffffffffffffp1023
+           Value: +1.7976931348623157e308 (NORMAL)
+  min-x =             0x1b7ffb77 :: Word32
+  max-x =             0x1b7ffb77 :: Word32
+  min-y =     0xffefffffffffffff :: Word64
+  max-y =     0xffefffffffffffff :: Word64
diff --git a/SBVTestSuite/GoldFiles/optFloat2.gold b/SBVTestSuite/GoldFiles/optFloat2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat2.gold
@@ -0,0 +1,108 @@
+Objective "min-x": Optimal model:
+  x     =              -Infinity :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 1 11111111 00000000000000000000000
+             Hex: FF80 0000
+       Precision: SP
+            Sign: Negative
+        Exponent: 128 (Stored: 255, Bias: 127)
+       Hex-float: -Infinity
+           Value: -Infinity
+  y     = 5.854952310409896e-270 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------F52-------------------------
+          Binary: 0 00010000000 1000101111101011111111001111010011101011010010001101
+             Hex: 0808 BEBF CF4E B48D
+       Precision: DP
+            Sign: Positive
+        Exponent: -895 (Stored: 128, Bias: 1023)
+       Hex-float: +0x1.8bebfcf4eb48dp-895
+           Value: +5.854952310409896e-270 (NORMAL)
+  min-x =             0x007fffff :: Word32
+  max-x =             0x007fffff :: Word32
+  min-y =     0x8808bebfcf4eb48d :: Word64
+  max-y =     0x8808bebfcf4eb48d :: Word64
+Objective "max-x": Optimal model:
+  x     =               Infinity :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 11111111 00000000000000000000000
+             Hex: 7F80 0000
+       Precision: SP
+            Sign: Positive
+        Exponent: 128 (Stored: 255, Bias: 127)
+       Hex-float: +Infinity
+           Value: +Infinity
+  y     = 5.854923399093713e-270 :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------F52-------------------------
+          Binary: 0 00010000000 1000101111101011011111001101010011101011010010000101
+             Hex: 0808 BEB7 CD4E B485
+       Precision: DP
+            Sign: Positive
+        Exponent: -895 (Stored: 128, Bias: 1023)
+       Hex-float: +0x1.8beb7cd4eb485p-895
+           Value: +5.854923399093713e-270 (NORMAL)
+  min-x =             0xff800000 :: Word32
+  max-x =             0xff800000 :: Word32
+  min-y =     0x8808beb7cd4eb485 :: Word64
+  max-y =     0x8808beb7cd4eb485 :: Word64
+Objective "min-y": Optimal model:
+  x     =         1.7237e-41 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 00000000 00000000011000000001101
+             Hex: 0000 300D
+       Precision: SP
+            Sign: Positive
+        Exponent: -126 (Stored: 0, Bias: 126)
+       Hex-float: +0x1.8068p-136
+           Value: +1.7237e-41 (DENORMAL)
+  y     =          -Infinity :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------F52-------------------------
+          Binary: 1 11111111111 0000000000000000000000000000000000000000000000000000
+             Hex: FFF0 0000 0000 0000
+       Precision: DP
+            Sign: Negative
+        Exponent: 1024 (Stored: 2047, Bias: 1023)
+       Hex-float: -Infinity
+           Value: -Infinity
+  min-x =         0x8000300d :: Word32
+  max-x =         0x8000300d :: Word32
+  min-y = 0x000fffffffffffff :: Word64
+  max-y = 0x000fffffffffffff :: Word64
+Objective "max-y": Optimal model:
+  x     =         1.7237e-41 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 00000000 00000000011000000001101
+             Hex: 0000 300D
+       Precision: SP
+            Sign: Positive
+        Exponent: -126 (Stored: 0, Bias: 126)
+       Hex-float: +0x1.8068p-136
+           Value: +1.7237e-41 (DENORMAL)
+  y     =           Infinity :: Double
+                  6    5          4         3         2         1         0
+                  3 21098765432 1098765432109876543210987654321098765432109876543210
+                  S ----E11---- ------------------------F52-------------------------
+          Binary: 0 11111111111 0000000000000000000000000000000000000000000000000000
+             Hex: 7FF0 0000 0000 0000
+       Precision: DP
+            Sign: Positive
+        Exponent: 1024 (Stored: 2047, Bias: 1023)
+       Hex-float: +Infinity
+           Value: +Infinity
+  min-x =         0x8000300d :: Word32
+  max-x =         0x8000300d :: Word32
+  min-y = 0xfff0000000000000 :: Word64
+  max-y = 0xfff0000000000000 :: Word64
diff --git a/SBVTestSuite/GoldFiles/optFloat3.gold b/SBVTestSuite/GoldFiles/optFloat3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat3.gold
@@ -0,0 +1,35 @@
+Optimal model:
+  max-x+y        = 3.4028235e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 11111110 11111111111111111111111
+             Hex: 7F7F FFFF
+       Precision: SP
+            Sign: Positive
+        Exponent: 127 (Stored: 254, Bias: 127)
+       Hex-float: +0x1.fffffep127
+           Value: +3.4028235e38 (NORMAL)
+  x              = 1.7014117e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 11111101 11111111111111111111111
+             Hex: 7EFF FFFF
+       Precision: SP
+            Sign: Positive
+        Exponent: 126 (Stored: 253, Bias: 127)
+       Hex-float: +0x1.fffffep126
+           Value: +1.7014117e38 (NORMAL)
+  y              = 1.7014117e38 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 11111101 11111111111111111111111
+             Hex: 7EFF FFFF
+       Precision: SP
+            Sign: Positive
+        Exponent: 126 (Stored: 253, Bias: 127)
+       Hex-float: +0x1.fffffep126
+           Value: +1.7014117e38 (NORMAL)
+  metric-max-x+y =   0xff7fffff :: Word32
diff --git a/SBVTestSuite/GoldFiles/optFloat4.gold b/SBVTestSuite/GoldFiles/optFloat4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optFloat4.gold
@@ -0,0 +1,35 @@
+Optimal model:
+  min-x+y        =    3.0e-45 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 00000000 00000000000000000000010
+             Hex: 0000 0002
+       Precision: SP
+            Sign: Positive
+        Exponent: -126 (Stored: 0, Bias: 126)
+       Hex-float: +0x1p-148
+           Value: +3.0e-45 (DENORMAL)
+  x              =    1.0e-45 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 00000000 00000000000000000000001
+             Hex: 0000 0001
+       Precision: SP
+            Sign: Positive
+        Exponent: -126 (Stored: 0, Bias: 126)
+       Hex-float: +0x1p-149
+           Value: +1.0e-45 (DENORMAL)
+  y              =    1.0e-45 :: Float
+                  3  2          1         0
+                  1 09876543 21098765432109876543210
+                  S ---E8--- ----------F23----------
+          Binary: 0 00000000 00000000000000000000001
+             Hex: 0000 0001
+       Precision: SP
+            Sign: Positive
+        Exponent: -126 (Stored: 0, Bias: 126)
+       Hex-float: +0x1p-149
+           Value: +1.0e-45 (DENORMAL)
+  metric-min-x+y = 0x80000002 :: Word32
diff --git a/SBVTestSuite/GoldFiles/optTuple1.gold b/SBVTestSuite/GoldFiles/optTuple1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/optTuple1.gold
@@ -0,0 +1,4 @@
+Optimal model:
+  p         = (44,36) :: (Integer, Integer)
+  max-p^._1 =      44 :: Integer
+  max-p^._2 =      36 :: Integer
diff --git a/SBVTestSuite/GoldFiles/pbAtLeast.gold b/SBVTestSuite/GoldFiles/pbAtLeast.gold
--- a/SBVTestSuite/GoldFiles/pbAtLeast.gold
+++ b/SBVTestSuite/GoldFiles/pbAtLeast.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
 [GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
diff --git a/SBVTestSuite/GoldFiles/pbAtMost.gold b/SBVTestSuite/GoldFiles/pbAtMost.gold
--- a/SBVTestSuite/GoldFiles/pbAtMost.gold
+++ b/SBVTestSuite/GoldFiles/pbAtMost.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
 [GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
diff --git a/SBVTestSuite/GoldFiles/pbEq.gold b/SBVTestSuite/GoldFiles/pbEq.gold
--- a/SBVTestSuite/GoldFiles/pbEq.gold
+++ b/SBVTestSuite/GoldFiles/pbEq.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s11 () Int 1)
 [GOOD] (define-fun s12 () Int 0)
diff --git a/SBVTestSuite/GoldFiles/pbEq2.gold b/SBVTestSuite/GoldFiles/pbEq2.gold
--- a/SBVTestSuite/GoldFiles/pbEq2.gold
+++ b/SBVTestSuite/GoldFiles/pbEq2.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Bool) ; tracks user variable "b0"
diff --git a/SBVTestSuite/GoldFiles/pbExactly.gold b/SBVTestSuite/GoldFiles/pbExactly.gold
--- a/SBVTestSuite/GoldFiles/pbExactly.gold
+++ b/SBVTestSuite/GoldFiles/pbExactly.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
 [GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
diff --git a/SBVTestSuite/GoldFiles/pbGe.gold b/SBVTestSuite/GoldFiles/pbGe.gold
--- a/SBVTestSuite/GoldFiles/pbGe.gold
+++ b/SBVTestSuite/GoldFiles/pbGe.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s11 () Int 1)
 [GOOD] (define-fun s12 () Int 0)
diff --git a/SBVTestSuite/GoldFiles/pbLe.gold b/SBVTestSuite/GoldFiles/pbLe.gold
--- a/SBVTestSuite/GoldFiles/pbLe.gold
+++ b/SBVTestSuite/GoldFiles/pbLe.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s11 () Int 1)
 [GOOD] (define-fun s12 () Int 0)
diff --git a/SBVTestSuite/GoldFiles/pbMutexed.gold b/SBVTestSuite/GoldFiles/pbMutexed.gold
--- a/SBVTestSuite/GoldFiles/pbMutexed.gold
+++ b/SBVTestSuite/GoldFiles/pbMutexed.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
 [GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
diff --git a/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold b/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold
--- a/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold
+++ b/SBVTestSuite/GoldFiles/pbStronglyMutexed.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s11 () (_ BitVec 32) #x00000001)
 [GOOD] (define-fun s12 () (_ BitVec 32) #x00000000)
diff --git a/SBVTestSuite/GoldFiles/qEnum1.gold b/SBVTestSuite/GoldFiles/qEnum1.gold
--- a/SBVTestSuite/GoldFiles/qEnum1.gold
+++ b/SBVTestSuite/GoldFiles/qEnum1.gold
@@ -7,11 +7,12 @@
 [GOOD] (set-option :produce-models true)
 [GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-datatypes () ((BinOp (Plus) (Minus) (Times))))
+[GOOD] (declare-datatypes ((BinOp 0)) (((Plus) (Minus) (Times))))
 [GOOD] (define-fun BinOp_constrIndex ((x BinOp)) Int
           (ite (= x Plus) 0 (ite (= x Minus) 1 2))
        )
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () BinOp) ; tracks user variable "p"
diff --git a/SBVTestSuite/GoldFiles/qUninterp1.gold b/SBVTestSuite/GoldFiles/qUninterp1.gold
--- a/SBVTestSuite/GoldFiles/qUninterp1.gold
+++ b/SBVTestSuite/GoldFiles/qUninterp1.gold
@@ -9,6 +9,7 @@
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] (declare-sort L 0)  ; N.B. Uninterpreted: L.B: not a nullary constructor
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () L)
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_contradiction_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_satisfiable_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsexists_thm_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s1 ((_ BitVec 8)) (_ BitVec 8)) ; tracks user variable "y"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_contradiction_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s1 ((_ BitVec 8)) (_ BitVec 8)) ; tracks user variable "y"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_satisfiable_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s1 ((_ BitVec 8)) (_ BitVec 8)) ; tracks user variable "y"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_existsforall_thm_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s1 ((_ BitVec 8)) (_ BitVec 8)) ; tracks user variable "y"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_contradiction_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_satisfiable_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallexists_thm_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_contradiction_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_satisfiable_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_prove_forallforall_thm_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_contradiction_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_satisfiable_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsexists_thm_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_contradiction_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_satisfiable_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_existsforall_thm_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s1 ((_ BitVec 8)) (_ BitVec 8)) ; tracks user variable "y"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_contradiction_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s1 ((_ BitVec 8)) (_ BitVec 8)) ; tracks user variable "y"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_satisfiable_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s1 ((_ BitVec 8)) (_ BitVec 8)) ; tracks user variable "y"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallexists_thm_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s1 ((_ BitVec 8)) (_ BitVec 8)) ; tracks user variable "y"
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_contradiction_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_satisfiable_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 8) #x01)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_c.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold
--- a/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold
+++ b/SBVTestSuite/GoldFiles/quantified_sat_forallforall_thm_p.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic BV)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/query1.gold b/SBVTestSuite/GoldFiles/query1.gold
--- a/SBVTestSuite/GoldFiles/query1.gold
+++ b/SBVTestSuite/GoldFiles/query1.gold
@@ -7,7 +7,6 @@
 [GOOD] (set-option :produce-unsat-cores true)
 [GOOD] (set-option :produce-unsat-assumptions true)
 [GOOD] (set-option :produce-proofs true)
-[GOOD] (set-option :produce-interpolants true)
 [GOOD] (set-option :random-seed 123)
 [GOOD] (set-option :produce-assertions true)
 [GOOD] (set-option :smt.mbqi true)
@@ -18,6 +17,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s6 () Int 0)
 [GOOD] ; --- skolem constants ---
@@ -54,19 +54,17 @@
 [RECV] true
 [SEND] (get-option :produce-proofs)
 [RECV] true
-[SEND] (get-option :produce-interpolants)
-[RECV] true
 [SEND] (get-option :produce-unsat-assumptions)
 [RECV] unsupported
 [SEND] (get-option :produce-unsat-cores)
-[SKIP] ; :produce-unsat-assumptions line: 42 position: 0
+[SKIP] ; :produce-unsat-assumptions line: 40 position: 0
 [RECV] true
 [SEND] (get-option :random-seed)
 [RECV] 123
 [SEND] (get-option :reproducible-resource-limit)
 [RECV] unsupported
 [SEND] (get-option :verbosity)
-[SKIP] ; :reproducible-resource-limit line: 45 position: 0
+[SKIP] ; :reproducible-resource-limit line: 43 position: 0
 [RECV] 0
 [SEND] (get-option :smt.mbqi)
 [RECV] true
@@ -110,10 +108,10 @@
 [SEND] (get-info :memory)
 [RECV] unsupported
 [SEND] (get-info :time)
-[SKIP] ; :memory line: 71 position: 0
+[SKIP] ; :memory line: 69 position: 0
 [RECV] unsupported
 [SEND] (get-value (s0))
-[SKIP] ; :time line: 72 position: 0
+[SKIP] ; :time line: 70 position: 0
 [RECV] ((s0 5))
 [SEND] (get-value (s1))
 [RECV] ((s1 1))
@@ -151,20 +149,20 @@
        (declare-fun bey () Bool)
        (declare-fun hey () Bool)
        (proof
-       (let (($x177 (<= s0 6)))
-        (let (($x178 (not $x177)))
-        (let (($x239 (or (not bey) $x178)))
-        (let ((@x237 (monotonicity (rewrite (= (> s0 6) $x178)) (= (=> bey (> s0 6)) (=> bey $x178)))))
-        (let ((@x243 (trans @x237 (rewrite (= (=> bey $x178) $x239)) (= (=> bey (> s0 6)) $x239))))
-        (let ((@x244 (mp (asserted (=> bey (> s0 6))) @x243 $x239)))
-        (let (($x256 (>= s0 6)))
-        (let (($x255 (not $x256)))
-        (let (($x265 (or (not hey) $x255)))
-        (let ((@x258 (monotonicity (rewrite (= (<= 6 s0) $x256)) (= (not (<= 6 s0)) $x255))))
-        (let ((@x260 (trans (rewrite (= (< s0 6) (not (<= 6 s0)))) @x258 (= (< s0 6) $x255))))
-        (let ((@x269 (trans (monotonicity @x260 (= (=> hey (< s0 6)) (=> hey $x255))) (rewrite (= (=> hey $x255) $x265)) (= (=> hey (< s0 6)) $x265))))
-        (let ((@x270 (mp (asserted (=> hey (< s0 6))) @x269 $x265)))
-        (unit-resolution ((_ th-lemma arith farkas 1 1) (or $x256 $x177)) (unit-resolution @x270 (asserted hey) $x255) (unit-resolution @x244 (asserted bey) $x178) false))))))))))))))))
+       (let (($x232 (<= s0 6)))
+        (let (($x233 (not $x232)))
+        (let (($x240 (or (not bey) $x233)))
+        (let ((@x238 (monotonicity (rewrite (= (> s0 6) $x233)) (= (=> bey (> s0 6)) (=> bey $x233)))))
+        (let ((@x244 (trans @x238 (rewrite (= (=> bey $x233) $x240)) (= (=> bey (> s0 6)) $x240))))
+        (let ((@x245 (mp (asserted (=> bey (> s0 6))) @x244 $x240)))
+        (let (($x257 (>= s0 6)))
+        (let (($x256 (not $x257)))
+        (let (($x266 (or (not hey) $x256)))
+        (let ((@x259 (monotonicity (rewrite (= (<= 6 s0) $x257)) (= (not (<= 6 s0)) $x256))))
+        (let ((@x261 (trans (rewrite (= (< s0 6) (not (<= 6 s0)))) @x259 (= (< s0 6) $x256))))
+        (let ((@x270 (trans (monotonicity @x261 (= (=> hey (< s0 6)) (=> hey $x256))) (rewrite (= (=> hey $x256) $x266)) (= (=> hey (< s0 6)) $x266))))
+        (let ((@x271 (mp (asserted (=> hey (< s0 6))) @x270 $x266)))
+        (unit-resolution ((_ th-lemma arith farkas 1 1) (or $x257 $x232)) (unit-resolution @x271 (asserted hey) $x256) (unit-resolution @x245 (asserted bey) $x233) false))))))))))))))))
 [SEND, TimeOut: 90000ms] (get-assertions)
 
 [RECV] ((! s7 :named |a > 0|)
diff --git a/SBVTestSuite/GoldFiles/queryArrays1.gold b/SBVTestSuite/GoldFiles/queryArrays1.gold
--- a/SBVTestSuite/GoldFiles/queryArrays1.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays1.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "a1"
diff --git a/SBVTestSuite/GoldFiles/queryArrays2.gold b/SBVTestSuite/GoldFiles/queryArrays2.gold
--- a/SBVTestSuite/GoldFiles/queryArrays2.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays2.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_UFBV) ; NB. User specified.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "i"
diff --git a/SBVTestSuite/GoldFiles/queryArrays3.gold b/SBVTestSuite/GoldFiles/queryArrays3.gold
--- a/SBVTestSuite/GoldFiles/queryArrays3.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays3.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_UFBV) ; NB. User specified.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "i"
diff --git a/SBVTestSuite/GoldFiles/queryArrays4.gold b/SBVTestSuite/GoldFiles/queryArrays4.gold
--- a/SBVTestSuite/GoldFiles/queryArrays4.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays4.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic QF_UFBV) ; NB. User specified.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "i"
diff --git a/SBVTestSuite/GoldFiles/queryArrays5.gold b/SBVTestSuite/GoldFiles/queryArrays5.gold
--- a/SBVTestSuite/GoldFiles/queryArrays5.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays5.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/queryArrays6.gold b/SBVTestSuite/GoldFiles/queryArrays6.gold
--- a/SBVTestSuite/GoldFiles/queryArrays6.gold
+++ b/SBVTestSuite/GoldFiles/queryArrays6.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/query_Chars1.gold b/SBVTestSuite/GoldFiles/query_Chars1.gold
--- a/SBVTestSuite/GoldFiles/query_Chars1.gold
+++ b/SBVTestSuite/GoldFiles/query_Chars1.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () Int 65)
 [GOOD] (define-fun s4 () Int 66)
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant1.gold b/SBVTestSuite/GoldFiles/query_Interpolant1.gold
--- a/SBVTestSuite/GoldFiles/query_Interpolant1.gold
+++ b/SBVTestSuite/GoldFiles/query_Interpolant1.gold
@@ -9,6 +9,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/query_Interpolant2.gold b/SBVTestSuite/GoldFiles/query_Interpolant2.gold
--- a/SBVTestSuite/GoldFiles/query_Interpolant2.gold
+++ b/SBVTestSuite/GoldFiles/query_Interpolant2.gold
@@ -9,6 +9,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/query_ListOfMaybe.gold b/SBVTestSuite/GoldFiles/query_ListOfMaybe.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_ListOfMaybe.gold
@@ -0,0 +1,63 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () Int 1)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Seq (SBVMaybe (_ BitVec 8)))) ; tracks user variable "lst"
+[GOOD] (declare-fun s4 () (SBVMaybe (_ BitVec 8))) ; tracks user variable "__internal_sbv_s4"
+[GOOD] (declare-fun s14 () (SBVMaybe (_ BitVec 8))) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int (seq.len s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () (Seq (SBVMaybe (_ BitVec 8))) (seq.unit s4))
+[GOOD] (define-fun s8 () (Seq (SBVMaybe (_ BitVec 8))) (seq.extract s0 s6 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (define-fun s10 () Bool (<= s1 s6))
+[GOOD] (define-fun s11 () Bool (or s9 s10))
+[GOOD] (define-fun s12 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe (_ BitVec 8)))) s4))
+[GOOD] (define-fun s13 () Bool (ite s12 false true))
+[GOOD] (define-fun s15 () (Seq (SBVMaybe (_ BitVec 8))) (seq.unit s14))
+[GOOD] (define-fun s16 () Int (- s1 s7))
+[GOOD] (define-fun s17 () (Seq (SBVMaybe (_ BitVec 8))) (seq.extract s0 s7 s16))
+[GOOD] (define-fun s18 () (Seq (SBVMaybe (_ BitVec 8))) (seq.extract s17 s6 s7))
+[GOOD] (define-fun s19 () Bool (= s15 s18))
+[GOOD] (define-fun s20 () Int (seq.len s17))
+[GOOD] (define-fun s21 () Bool (<= s20 s6))
+[GOOD] (define-fun s22 () Bool (or s19 s21))
+[GOOD] (define-fun s23 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe (_ BitVec 8)))) s14))
+[GOOD] (define-fun s24 () Bool (ite s23 true false))
+[GOOD] (assert s3)
+[GOOD] (assert s11)
+[GOOD] (assert s13)
+[GOOD] (assert s22)
+[GOOD] (assert s24)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit (just_SBVMaybe #x00)) (seq.unit nothing_SBVMaybe))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+[Just '\NUL',Nothing]
diff --git a/SBVTestSuite/GoldFiles/query_ListOfSum.gold b/SBVTestSuite/GoldFiles/query_ListOfSum.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_ListOfSum.gold
@@ -0,0 +1,63 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 2)
+[GOOD] (define-fun s6 () Int 0)
+[GOOD] (define-fun s7 () Int 1)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Seq (SBVEither Int (_ BitVec 8)))) ; tracks user variable "lst"
+[GOOD] (declare-fun s4 () (SBVEither Int (_ BitVec 8))) ; tracks user variable "__internal_sbv_s4"
+[GOOD] (declare-fun s14 () (SBVEither Int (_ BitVec 8))) ; tracks user variable "__internal_sbv_s14"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int (seq.len s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s5 () (Seq (SBVEither Int (_ BitVec 8))) (seq.unit s4))
+[GOOD] (define-fun s8 () (Seq (SBVEither Int (_ BitVec 8))) (seq.extract s0 s6 s7))
+[GOOD] (define-fun s9 () Bool (= s5 s8))
+[GOOD] (define-fun s10 () Bool (<= s1 s6))
+[GOOD] (define-fun s11 () Bool (or s9 s10))
+[GOOD] (define-fun s12 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int (_ BitVec 8)))) s4))
+[GOOD] (define-fun s13 () Bool (ite s12 true false))
+[GOOD] (define-fun s15 () (Seq (SBVEither Int (_ BitVec 8))) (seq.unit s14))
+[GOOD] (define-fun s16 () Int (- s1 s7))
+[GOOD] (define-fun s17 () (Seq (SBVEither Int (_ BitVec 8))) (seq.extract s0 s7 s16))
+[GOOD] (define-fun s18 () (Seq (SBVEither Int (_ BitVec 8))) (seq.extract s17 s6 s7))
+[GOOD] (define-fun s19 () Bool (= s15 s18))
+[GOOD] (define-fun s20 () Int (seq.len s17))
+[GOOD] (define-fun s21 () Bool (<= s20 s6))
+[GOOD] (define-fun s22 () Bool (or s19 s21))
+[GOOD] (define-fun s23 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int (_ BitVec 8)))) s14))
+[GOOD] (define-fun s24 () Bool (ite s23 false true))
+[GOOD] (assert s3)
+[GOOD] (assert s11)
+[GOOD] (assert s13)
+[GOOD] (assert s22)
+[GOOD] (assert s24)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (seq.++ (seq.unit (left_SBVEither 3)) (seq.unit (right_SBVEither #x00)))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+[Left 3,Right '\NUL']
diff --git a/SBVTestSuite/GoldFiles/query_Lists1.gold b/SBVTestSuite/GoldFiles/query_Lists1.gold
--- a/SBVTestSuite/GoldFiles/query_Lists1.gold
+++ b/SBVTestSuite/GoldFiles/query_Lists1.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4) (seq.unit 5)))
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/query_Maybe.gold b/SBVTestSuite/GoldFiles/query_Maybe.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Maybe.gold
@@ -0,0 +1,40 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVMaybe Int)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int (get_just_SBVMaybe s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s0))
+[GOOD] (define-fun s5 () Bool (ite s4 false s3))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (just_SBVMaybe 1)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Just 1
diff --git a/SBVTestSuite/GoldFiles/query_Strings1.gold b/SBVTestSuite/GoldFiles/query_Strings1.gold
--- a/SBVTestSuite/GoldFiles/query_Strings1.gold
+++ b/SBVTestSuite/GoldFiles/query_Strings1.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () String) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/query_SumMaybeBoth.gold b/SBVTestSuite/GoldFiles/query_SumMaybeBoth.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_SumMaybeBoth.gold
@@ -0,0 +1,48 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] (declare-fun s0 () (SBVEither Int Int))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] (define-fun s2 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Int))) s0))
+[GOOD] (define-fun s3 () Bool (ite s2 true false))
+[GOOD] (assert s3)
+[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s1))
+[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (left_SBVEither 0)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (just_SBVMaybe 1)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Left 0,Just 1)
diff --git a/SBVTestSuite/GoldFiles/query_Sums.gold b/SBVTestSuite/GoldFiles/query_Sums.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_Sums.gold
@@ -0,0 +1,40 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVEither Int (_ BitVec 8))) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int (get_left_SBVEither s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int (_ BitVec 8)))) s0))
+[GOOD] (define-fun s5 () Bool (ite s4 s3 false))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (left_SBVEither 1)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Left 1
diff --git a/SBVTestSuite/GoldFiles/query_Tuples1.gold b/SBVTestSuite/GoldFiles/query_Tuples1.gold
--- a/SBVTestSuite/GoldFiles/query_Tuples1.gold
+++ b/SBVTestSuite/GoldFiles/query_Tuples1.gold
@@ -5,12 +5,15 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
                                                          (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () Int 1)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/query_Tuples2.gold b/SBVTestSuite/GoldFiles/query_Tuples2.gold
--- a/SBVTestSuite/GoldFiles/query_Tuples2.gold
+++ b/SBVTestSuite/GoldFiles/query_Tuples2.gold
@@ -5,13 +5,16 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
-[GOOD] (declare-datatypes () ((SBVTuple0 SBVTuple0)))
+[GOOD] (declare-datatypes ((SBVTuple0 0)) (((mkSBVTuple0))))
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
                                                          (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () (_ BitVec 8) #x63)
 [GOOD] ; --- skolem constants ---
@@ -29,7 +32,7 @@
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
-[RECV] ((s0 (mkSBVTuple2 0 (mkSBVTuple2 #x63 SBVTuple0))))
+[RECV] ((s0 (mkSBVTuple2 0 (mkSBVTuple2 #x63 mkSBVTuple0))))
 *** Solver   : Z3
 *** Exit code: ExitSuccess
 
diff --git a/SBVTestSuite/GoldFiles/query_abc.gold b/SBVTestSuite/GoldFiles/query_abc.gold
--- a/SBVTestSuite/GoldFiles/query_abc.gold
+++ b/SBVTestSuite/GoldFiles/query_abc.gold
@@ -8,6 +8,7 @@
 [ISSUE] (set-logic ALL) ; external query, using all logics.
 [ISSUE] ; --- uninterpreted sorts ---
 [ISSUE] ; --- tuples ---
+[ISSUE] ; --- sums ---
 [ISSUE] ; --- literal constants ---
 [ISSUE] (define-fun s2 () (_ BitVec 32) #x00000000)
 [ISSUE] ; --- skolem constants ---
@@ -23,6 +24,20 @@
 [ISSUE] (define-fun s4 () Bool (bvsgt s1 s2))
 [ISSUE] (assert s3)
 [ISSUE] (assert s4)
+[FIRE] (define-fun s5 () (_ BitVec 32) #x00000002)
+[FIRE] (define-fun s7 () (_ BitVec 32) #x0000000f)
+[FIRE] (define-fun s6 () (_ BitVec 32) (bvadd s0 s5))
+[FIRE] (define-fun s8 () Bool (bvsle s6 s7))
+[FIRE] (assert s8)
+[FIRE] (define-fun s9 () Bool (bvslt s0 s5))
+[FIRE] (assert s9)
+[FIRE] (define-fun s10 () Bool (bvslt s1 s5))
+[FIRE] (assert s10)
+[FIRE] (define-fun s12 () (_ BitVec 32) #x0000000c)
+[FIRE] (define-fun s11 () (_ BitVec 32) (bvadd s0 s1))
+[FIRE] (define-fun s13 () Bool (bvslt s11 s12))
+[FIRE] (assert s13)
+[FIRE] (assert s9)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
diff --git a/SBVTestSuite/GoldFiles/query_boolector.gold b/SBVTestSuite/GoldFiles/query_boolector.gold
--- a/SBVTestSuite/GoldFiles/query_boolector.gold
+++ b/SBVTestSuite/GoldFiles/query_boolector.gold
@@ -7,6 +7,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/query_cvc4.gold b/SBVTestSuite/GoldFiles/query_cvc4.gold
--- a/SBVTestSuite/GoldFiles/query_cvc4.gold
+++ b/SBVTestSuite/GoldFiles/query_cvc4.gold
@@ -7,6 +7,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/query_mathsat.gold b/SBVTestSuite/GoldFiles/query_mathsat.gold
--- a/SBVTestSuite/GoldFiles/query_mathsat.gold
+++ b/SBVTestSuite/GoldFiles/query_mathsat.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/query_sumMergeEither1.gold b/SBVTestSuite/GoldFiles/query_sumMergeEither1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_sumMergeEither1.gold
@@ -0,0 +1,44 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] (declare-fun s0 () (SBVEither Int Bool))
+[GOOD] (declare-fun s1 () (SBVEither Int Bool))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () (SBVEither Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s3))
+[GOOD] (define-fun s5 () Bool (ite s4 true false))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (left_SBVEither 0)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (right_SBVEither false)))
+[SEND] (get-value (s2))
+[RECV] ((s2 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Left 0,Right False,True)
diff --git a/SBVTestSuite/GoldFiles/query_sumMergeEither2.gold b/SBVTestSuite/GoldFiles/query_sumMergeEither2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_sumMergeEither2.gold
@@ -0,0 +1,44 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] (declare-fun s0 () (SBVEither Int Bool))
+[GOOD] (declare-fun s1 () (SBVEither Int Bool))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () (SBVEither Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s3))
+[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (right_SBVEither false)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (right_SBVEither false)))
+[SEND] (get-value (s2))
+[RECV] ((s2 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Right False,Right False,True)
diff --git a/SBVTestSuite/GoldFiles/query_sumMergeMaybe1.gold b/SBVTestSuite/GoldFiles/query_sumMergeMaybe1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_sumMergeMaybe1.gold
@@ -0,0 +1,44 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] (declare-fun s0 () (SBVMaybe Int))
+[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () (SBVMaybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s3))
+[GOOD] (define-fun s5 () Bool (ite s4 true false))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 nothing_SBVMaybe))
+[SEND] (get-value (s1))
+[RECV] ((s1 (just_SBVMaybe 0)))
+[SEND] (get-value (s2))
+[RECV] ((s2 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Nothing,Just 0,True)
diff --git a/SBVTestSuite/GoldFiles/query_sumMergeMaybe2.gold b/SBVTestSuite/GoldFiles/query_sumMergeMaybe2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_sumMergeMaybe2.gold
@@ -0,0 +1,44 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; external query, using all logics.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] (declare-fun s0 () (SBVMaybe Int))
+[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] (define-fun s3 () (SBVMaybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s3))
+[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (just_SBVMaybe 0)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (just_SBVMaybe 0)))
+[SEND] (get-value (s2))
+[RECV] ((s2 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+(Just 0,Just 0,True)
diff --git a/SBVTestSuite/GoldFiles/query_uiSat_test1.gold b/SBVTestSuite/GoldFiles/query_uiSat_test1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_uiSat_test1.gold
@@ -0,0 +1,35 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; NB. User specified.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q1 (Bool) Bool)
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s0 () Bool (q1 false))
+[GOOD] (define-fun s1 () Bool (= false s0))
+[GOOD] (define-fun s2 () Bool (q1 true))
+[GOOD] (assert s1)
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [], modelUIFuns = [("q1",(SBool -> SBool,([([True :: Bool],True :: Bool)],False :: Bool)))]}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/query_uiSat_test2.gold b/SBVTestSuite/GoldFiles/query_uiSat_test2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_uiSat_test2.gold
@@ -0,0 +1,45 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; NB. User specified.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q2 (Bool Bool) Bool)
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s0 () Bool (q2 false true))
+[GOOD] (define-fun s1 () Bool (= false s0))
+[GOOD] (define-fun s2 () Bool (q2 true true))
+[GOOD] (define-fun s3 () Bool (q2 true false))
+[GOOD] (assert s1)
+[GOOD] (assert s2)
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 (not x!2)) (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [], modelUIFuns = [("q2",(SBool -> SBool -> SBool,([([True :: Bool,False :: Bool],True :: Bool),([True :: Bool,True :: Bool],True :: Bool)],False :: Bool)))]}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/query_uisatex1.gold b/SBVTestSuite/GoldFiles/query_uisatex1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_uisatex1.gold
@@ -0,0 +1,185 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 2)
+[GOOD] (define-fun s3 () Int 12)
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] (define-fun s7 () Int 75)
+[GOOD] (define-fun s9 () Int (- 3))
+[GOOD] (define-fun s11 () Int 9)
+[GOOD] (define-fun s14 () Int 1)
+[GOOD] (define-fun s17 () Int 0)
+[GOOD] (define-fun s20 () Int 5)
+[GOOD] (define-fun s22 () Int 7)
+[GOOD] (define-fun s24 () Int 6)
+[GOOD] (define-fun s32 () Int 121)
+[GOOD] (define-fun s37 () Int 8)
+[GOOD] (define-fun s62 () Int 21)
+[GOOD] (define-fun s67 () Int 210)
+[GOOD] (define-fun s28 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 4508877.0 524288.0)))
+[GOOD] (define-fun s31 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 5033165.0 524288.0)))
+[GOOD] (define-fun s39 () (_ FloatingPoint  8 24) (_ +oo 8 24))
+[GOOD] (define-fun s44 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 78.0 1.0)))
+[GOOD] (define-fun s48 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 92.0 1.0)))
+[GOOD] (define-fun s53 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 7.0 2.0)))
+[GOOD] (define-fun s41 () (_ BitVec 8) #x63)
+[GOOD] (define-fun s50 () (_ BitVec 8) #x72)
+[GOOD] (define-fun s42 () String "hey")
+[GOOD] (define-fun s46 () String "tey")
+[GOOD] (define-fun s51 () String "foo")
+[GOOD] (define-fun s55 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] (define-fun s59 () (Seq Int) (seq.++ (seq.unit 9) (seq.unit 5)))
+[GOOD] (define-fun s64 () (Seq Int) (seq.unit 5))
+[GOOD] (define-fun s56 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 8598323.0 1048576.0))) (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 3.0 1.0)))))
+[GOOD] (define-fun s60 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 8598323.0 1048576.0))) (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 9.0 1.0)))))
+[GOOD] (define-fun s65 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 8598323.0 1048576.0))) (seq.unit (_ +zero 8 24))))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q1 (Int) Int)
+[GOOD] (declare-fun q2 (Bool Int) Int)
+[GOOD] (declare-fun q3 ((_ FloatingPoint  8 24) Bool Int) (_ FloatingPoint  8 24))
+[GOOD] (declare-fun q4 ((_ BitVec 8) String) (_ FloatingPoint  8 24))
+[GOOD] (declare-fun q5 ((Seq Int) (Seq (_ FloatingPoint  8 24))) Int)
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Int (q1 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s6 () Int (q1 s5))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s10 () Int (q1 s9))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s13 () Int (q1 s0))
+[GOOD] (define-fun s15 () Int (+ s0 s14))
+[GOOD] (define-fun s16 () Bool (= s13 s15))
+[GOOD] (define-fun s18 () Int (q2 false s17))
+[GOOD] (define-fun s19 () Int (q2 true s5))
+[GOOD] (define-fun s21 () Bool (= s19 s20))
+[GOOD] (define-fun s23 () Int (q2 false s22))
+[GOOD] (define-fun s25 () Bool (= s23 s24))
+[GOOD] (define-fun s26 () Int (q2 false s3))
+[GOOD] (define-fun s27 () Bool (= s5 s26))
+[GOOD] (define-fun s29 () (_ FloatingPoint  8 24) (q3 s28 true s3))
+[GOOD] (define-fun s30 () Bool (fp.eq s28 s29))
+[GOOD] (define-fun s33 () (_ FloatingPoint  8 24) (q3 s31 true s32))
+[GOOD] (define-fun s34 () Bool (fp.isZero s33))
+[GOOD] (define-fun s35 () Bool (fp.isNegative s33))
+[GOOD] (define-fun s36 () Bool (and s34 s35))
+[GOOD] (define-fun s38 () (_ FloatingPoint  8 24) (q3 s31 false s37))
+[GOOD] (define-fun s40 () Bool (fp.eq s38 s39))
+[GOOD] (define-fun s43 () (_ FloatingPoint  8 24) (q4 s41 s42))
+[GOOD] (define-fun s45 () Bool (fp.eq s43 s44))
+[GOOD] (define-fun s47 () (_ FloatingPoint  8 24) (q4 s41 s46))
+[GOOD] (define-fun s49 () Bool (fp.eq s47 s48))
+[GOOD] (define-fun s52 () (_ FloatingPoint  8 24) (q4 s50 s51))
+[GOOD] (define-fun s54 () Bool (fp.eq s52 s53))
+[GOOD] (define-fun s57 () Int (q5 s55 s56))
+[GOOD] (define-fun s58 () Bool (= s22 s57))
+[GOOD] (define-fun s61 () Int (q5 s59 s60))
+[GOOD] (define-fun s63 () Bool (= s61 s62))
+[GOOD] (define-fun s66 () Int (q5 s64 s65))
+[GOOD] (define-fun s68 () Bool (= s66 s67))
+[GOOD] (assert s4)
+[GOOD] (assert s8)
+[GOOD] (assert s12)
+[GOOD] (assert s16)
+[GOOD] (assert s21)
+[GOOD] (assert s25)
+[GOOD] (assert s27)
+[GOOD] (assert s30)
+[GOOD] (assert s36)
+[GOOD] (assert s40)
+[GOOD] (assert s45)
+[GOOD] (assert s49)
+[GOOD] (assert s54)
+[GOOD] (assert s58)
+[GOOD] (assert s63)
+[GOOD] (assert s68)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Int))
+         (ite (= x!1 0) 1 (ite (= x!1 (- 3)) 9 (ite (= x!1 3) 75 12))))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Int))
+         (ite (and (not x!1) (= x!2 12)) 3 (ite (and (not x!1) (= x!2 7)) 6 5)))))
+[SEND] (get-value (q3))
+[RECV] ((q3 (lambda ((x!1 (_ FloatingPoint 8 24)) (x!2 Bool) (x!3 Int))
+         (ite (and (= x!1 (fp #b0 #x82 #b00110011001100110011010)) (not x!2) (= x!3 8))
+              (_ +oo 8 24)
+              (ite (and (= x!1 (fp #b0 #x82 #b00110011001100110011010))
+                        x!2
+                        (= x!3 121))
+                   (_ -zero 8 24)
+                   (fp #b0 #x82 #b00010011001100110011010))))))
+[SEND] (get-value (q4))
+[RECV] ((q4 (lambda ((x!1 (_ BitVec 8)) (x!2 String))
+         (ite (and (= x!1 #x72) (= x!2 "foo"))
+              (fp #b0 #x80 #b11000000000000000000000)
+              (ite (and (= x!1 #x63) (= x!2 "tey"))
+                   (fp #b0 #x85 #b01110000000000000000000)
+                   (fp #b0 #x85 #b00111000000000000000000))))))
+[SEND] (get-value (q5))
+[RECV] ((q5 (lambda ((x!1 (Seq Int)) (x!2 (Seq (_ FloatingPoint 8 24))))
+         (ite (and (= x!1 (seq.unit 5))
+                   (= x!2
+                      (seq.++ (seq.unit (fp #b0 #x82 #b00000110011001100110011))
+                              (seq.unit (_ +zero 8 24)))))
+              210
+              (ite (and (= x!1 (seq.++ (seq.unit 9) (seq.unit 5)))
+                        (= x!2
+                           (seq.++ (seq.unit (fp #b0 #x82 #b00000110011001100110011))
+                                   (seq.unit (fp #b0 #x82 #b00100000000000000000000)))))
+                   21
+                   7)))))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:
+Satisfiable. Model:
+  s0 = 0 :: Integer
+
+  q1 :: Integer -> Integer
+  q1 0    = 1 
+  q1 (-3) = 9 
+  q1 3    = 75
+  q1 _    = 12
+
+  q2 :: Bool -> Integer -> Integer
+  q2 False 12 = 3
+  q2 False 7  = 6
+  q2 _     _  = 5
+
+  q3 :: Float -> Bool -> Integer -> Float
+  q3 9.6 False 8   = Infinity
+  q3 9.6 True  121 = -0.0    
+  q3 _   _     _   = 8.6     
+
+  q4 :: Char -> String -> Float
+  q4 'r' "foo" = 3.5 
+  q4 'c' "tey" = 92.0
+  q4 _   _     = 78.0
+
+  q5 :: [Integer] -> [Float] -> Integer
+  q5 [5]   [8.2,0.0] = 210
+  q5 [9,5] [8.2,9.0] = 21 
+  q5 _     _         = 7  
+DONE!
diff --git a/SBVTestSuite/GoldFiles/query_uisatex2.gold b/SBVTestSuite/GoldFiles/query_uisatex2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/query_uisatex2.gold
@@ -0,0 +1,161 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () Int 2)
+[GOOD] (define-fun s3 () Int 12)
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] (define-fun s7 () Int 75)
+[GOOD] (define-fun s9 () Int (- 3))
+[GOOD] (define-fun s11 () Int 9)
+[GOOD] (define-fun s14 () Int 1)
+[GOOD] (define-fun s17 () Int 0)
+[GOOD] (define-fun s20 () Int 5)
+[GOOD] (define-fun s22 () Int 7)
+[GOOD] (define-fun s24 () Int 6)
+[GOOD] (define-fun s32 () Int 121)
+[GOOD] (define-fun s37 () Int 8)
+[GOOD] (define-fun s62 () Int 21)
+[GOOD] (define-fun s67 () Int 210)
+[GOOD] (define-fun s28 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 4508877.0 524288.0)))
+[GOOD] (define-fun s31 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 5033165.0 524288.0)))
+[GOOD] (define-fun s39 () (_ FloatingPoint  8 24) (_ +oo 8 24))
+[GOOD] (define-fun s44 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 78.0 1.0)))
+[GOOD] (define-fun s48 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 92.0 1.0)))
+[GOOD] (define-fun s53 () (_ FloatingPoint  8 24) ((_ to_fp 8 24) roundNearestTiesToEven (/ 7.0 2.0)))
+[GOOD] (define-fun s41 () (_ BitVec 8) #x63)
+[GOOD] (define-fun s50 () (_ BitVec 8) #x72)
+[GOOD] (define-fun s42 () String "hey")
+[GOOD] (define-fun s46 () String "tey")
+[GOOD] (define-fun s51 () String "foo")
+[GOOD] (define-fun s55 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
+[GOOD] (define-fun s59 () (Seq Int) (seq.++ (seq.unit 9) (seq.unit 5)))
+[GOOD] (define-fun s64 () (Seq Int) (seq.unit 5))
+[GOOD] (define-fun s56 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 8598323.0 1048576.0))) (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 3.0 1.0)))))
+[GOOD] (define-fun s60 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 8598323.0 1048576.0))) (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 9.0 1.0)))))
+[GOOD] (define-fun s65 () (Seq (_ FloatingPoint  8 24)) (seq.++ (seq.unit ((_ to_fp 8 24) roundNearestTiesToEven (/ 8598323.0 1048576.0))) (seq.unit (_ +zero 8 24))))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () Int)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q1 (Int) Int)
+[GOOD] (declare-fun q2 (Bool Int) Int)
+[GOOD] (declare-fun q3 ((_ FloatingPoint  8 24) Bool Int) (_ FloatingPoint  8 24))
+[GOOD] (declare-fun q4 ((_ BitVec 8) String) (_ FloatingPoint  8 24))
+[GOOD] (declare-fun q5 ((Seq Int) (Seq (_ FloatingPoint  8 24))) Int)
+[GOOD] (declare-fun q6 (Int) Bool)
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Int (q1 s1))
+[GOOD] (define-fun s4 () Bool (= s2 s3))
+[GOOD] (define-fun s6 () Int (q1 s5))
+[GOOD] (define-fun s8 () Bool (= s6 s7))
+[GOOD] (define-fun s10 () Int (q1 s9))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s13 () Int (q1 s0))
+[GOOD] (define-fun s15 () Int (+ s0 s14))
+[GOOD] (define-fun s16 () Bool (= s13 s15))
+[GOOD] (define-fun s18 () Int (q2 false s17))
+[GOOD] (define-fun s19 () Int (q2 true s5))
+[GOOD] (define-fun s21 () Bool (= s19 s20))
+[GOOD] (define-fun s23 () Int (q2 false s22))
+[GOOD] (define-fun s25 () Bool (= s23 s24))
+[GOOD] (define-fun s26 () Int (q2 false s3))
+[GOOD] (define-fun s27 () Bool (= s5 s26))
+[GOOD] (define-fun s29 () (_ FloatingPoint  8 24) (q3 s28 true s3))
+[GOOD] (define-fun s30 () Bool (fp.eq s28 s29))
+[GOOD] (define-fun s33 () (_ FloatingPoint  8 24) (q3 s31 true s32))
+[GOOD] (define-fun s34 () Bool (fp.isZero s33))
+[GOOD] (define-fun s35 () Bool (fp.isNegative s33))
+[GOOD] (define-fun s36 () Bool (and s34 s35))
+[GOOD] (define-fun s38 () (_ FloatingPoint  8 24) (q3 s31 false s37))
+[GOOD] (define-fun s40 () Bool (fp.eq s38 s39))
+[GOOD] (define-fun s43 () (_ FloatingPoint  8 24) (q4 s41 s42))
+[GOOD] (define-fun s45 () Bool (fp.eq s43 s44))
+[GOOD] (define-fun s47 () (_ FloatingPoint  8 24) (q4 s41 s46))
+[GOOD] (define-fun s49 () Bool (fp.eq s47 s48))
+[GOOD] (define-fun s52 () (_ FloatingPoint  8 24) (q4 s50 s51))
+[GOOD] (define-fun s54 () Bool (fp.eq s52 s53))
+[GOOD] (define-fun s57 () Int (q5 s55 s56))
+[GOOD] (define-fun s58 () Bool (= s22 s57))
+[GOOD] (define-fun s61 () Int (q5 s59 s60))
+[GOOD] (define-fun s63 () Bool (= s61 s62))
+[GOOD] (define-fun s66 () Int (q5 s64 s65))
+[GOOD] (define-fun s68 () Bool (= s66 s67))
+[GOOD] (define-fun s69 () Bool (q6 s17))
+[GOOD] (define-fun s70 () Bool (not s69))
+[GOOD] (define-fun s71 () Bool (or s69 s70))
+[GOOD] (assert s4)
+[GOOD] (assert s8)
+[GOOD] (assert s12)
+[GOOD] (assert s16)
+[GOOD] (assert s21)
+[GOOD] (assert s25)
+[GOOD] (assert s27)
+[GOOD] (assert s30)
+[GOOD] (assert s36)
+[GOOD] (assert s40)
+[GOOD] (assert s45)
+[GOOD] (assert s49)
+[GOOD] (assert s54)
+[GOOD] (assert s58)
+[GOOD] (assert s63)
+[GOOD] (assert s68)
+[GOOD] (assert s71)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Int))
+         (ite (= x!1 0) 1 (ite (= x!1 (- 3)) 9 (ite (= x!1 3) 75 12))))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Int))
+         (ite (and (not x!1) (= x!2 12)) 3 (ite (and (not x!1) (= x!2 7)) 6 5)))))
+[SEND] (get-value (q3))
+[RECV] ((q3 (lambda ((x!1 (_ FloatingPoint 8 24)) (x!2 Bool) (x!3 Int))
+         (ite (and (= x!1 (fp #b0 #x82 #b00110011001100110011010)) (not x!2) (= x!3 8))
+              (_ +oo 8 24)
+              (ite (and (= x!1 (fp #b0 #x82 #b00110011001100110011010))
+                        x!2
+                        (= x!3 121))
+                   (_ -zero 8 24)
+                   (fp #b0 #x82 #b00010011001100110011010))))))
+[SEND] (get-value (q4))
+[RECV] ((q4 (lambda ((x!1 (_ BitVec 8)) (x!2 String))
+         (ite (and (= x!1 #x72) (= x!2 "foo"))
+              (fp #b0 #x80 #b11000000000000000000000)
+              (ite (and (= x!1 #x63) (= x!2 "tey"))
+                   (fp #b0 #x85 #b01110000000000000000000)
+                   (fp #b0 #x85 #b00111000000000000000000))))))
+[SEND] (get-value (q5))
+[RECV] ((q5 (lambda ((x!1 (Seq Int)) (x!2 (Seq (_ FloatingPoint 8 24))))
+         (ite (and (= x!1 (seq.unit 5))
+                   (= x!2
+                      (seq.++ (seq.unit (fp #b0 #x82 #b00000110011001100110011))
+                              (seq.unit (_ +zero 8 24)))))
+              210
+              (ite (and (= x!1 (seq.++ (seq.unit 9) (seq.unit 5)))
+                        (= x!2
+                           (seq.++ (seq.unit (fp #b0 #x82 #b00000110011001100110011))
+                                   (seq.unit (fp #b0 #x82 #b00100000000000000000000)))))
+                   21
+                   7)))))
+[SEND] (get-value (q6))
+[RECV] ((q6 (lambda ((x!1 Int)) false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+ FINAL:
+(([(0,1),(-3,9),(3,75)],12),([((False,12),3),((False,7),6)],5),([((9.6,False,8),Infinity),((9.6,True,121),-0.0)],8.6),([(('r',"foo"),3.5),(('c',"tey"),92.0)],78.0),([(([5],[8.2,0.0]),210),(([9,5],[8.2,9.0]),21)],7),([],False))
+DONE!
diff --git a/SBVTestSuite/GoldFiles/query_yices.gold b/SBVTestSuite/GoldFiles/query_yices.gold
--- a/SBVTestSuite/GoldFiles/query_yices.gold
+++ b/SBVTestSuite/GoldFiles/query_yices.gold
@@ -7,6 +7,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/query_z3.gold b/SBVTestSuite/GoldFiles/query_z3.gold
--- a/SBVTestSuite/GoldFiles/query_z3.gold
+++ b/SBVTestSuite/GoldFiles/query_z3.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s2 () (_ BitVec 32) #x00000000)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/reverse.gold b/SBVTestSuite/GoldFiles/reverse.gold
--- a/SBVTestSuite/GoldFiles/reverse.gold
+++ b/SBVTestSuite/GoldFiles/reverse.gold
@@ -10,25 +10,26 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s13 () Int 1)
-[GOOD] (define-fun s53 () Int 0)
-[GOOD] (define-fun s11 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s12 () Int 0)
+[GOOD] (define-fun s15 () Int 1)
+[GOOD] (define-fun s14 () (Seq Int) (as seq.empty (Seq Int)))
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
 [GOOD] (declare-fun s2 () Int) ; tracks user variable "c"
 [GOOD] (declare-fun s3 () Int) ; tracks user variable "d"
-[GOOD] (declare-fun s50 () Int) ; tracks user variable "__internal_sbv_s50"
-[GOOD] (declare-fun s60 () Int) ; tracks user variable "__internal_sbv_s60"
-[GOOD] (declare-fun s69 () Int) ; tracks user variable "__internal_sbv_s69"
-[GOOD] (declare-fun s78 () Int) ; tracks user variable "__internal_sbv_s78"
-[GOOD] (declare-fun s87 () Int) ; tracks user variable "__internal_sbv_s87"
-[GOOD] (declare-fun s96 () Int) ; tracks user variable "__internal_sbv_s96"
-[GOOD] (declare-fun s105 () Int) ; tracks user variable "__internal_sbv_s105"
-[GOOD] (declare-fun s114 () Int) ; tracks user variable "__internal_sbv_s114"
+[GOOD] (declare-fun s52 () Int) ; tracks user variable "__internal_sbv_s52"
+[GOOD] (declare-fun s59 () Int) ; tracks user variable "__internal_sbv_s59"
+[GOOD] (declare-fun s67 () Int) ; tracks user variable "__internal_sbv_s67"
+[GOOD] (declare-fun s75 () Int) ; tracks user variable "__internal_sbv_s75"
+[GOOD] (declare-fun s83 () Int) ; tracks user variable "__internal_sbv_s83"
+[GOOD] (declare-fun s91 () Int) ; tracks user variable "__internal_sbv_s91"
+[GOOD] (declare-fun s99 () Int) ; tracks user variable "__internal_sbv_s99"
+[GOOD] (declare-fun s107 () Int) ; tracks user variable "__internal_sbv_s107"
+[GOOD] (declare-fun s115 () Int) ; tracks user variable "__internal_sbv_s115"
 [GOOD] (declare-fun s123 () Int) ; tracks user variable "__internal_sbv_s123"
-[GOOD] (declare-fun s132 () Int) ; tracks user variable "__internal_sbv_s132"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -42,138 +43,128 @@
 [GOOD] (define-fun s8 () (Seq Int) (seq.++ s6 s7))
 [GOOD] (define-fun s9 () (Seq Int) (seq.++ s5 s8))
 [GOOD] (define-fun s10 () (Seq Int) (seq.++ s4 s9))
-[GOOD] (define-fun s12 () Bool (= s10 s11))
-[GOOD] (define-fun s14 () Int (seq.len s10))
-[GOOD] (define-fun s15 () Int (- s14 s13))
-[GOOD] (define-fun s16 () (Seq Int) (seq.extract s10 s13 s15))
-[GOOD] (define-fun s17 () Bool (= s11 s16))
-[GOOD] (define-fun s18 () Int (seq.len s16))
-[GOOD] (define-fun s19 () Int (- s18 s13))
-[GOOD] (define-fun s20 () (Seq Int) (seq.extract s16 s13 s19))
-[GOOD] (define-fun s21 () Bool (= s11 s20))
-[GOOD] (define-fun s22 () Int (seq.len s20))
-[GOOD] (define-fun s23 () Int (- s22 s13))
-[GOOD] (define-fun s24 () (Seq Int) (seq.extract s20 s13 s23))
-[GOOD] (define-fun s25 () Bool (= s11 s24))
-[GOOD] (define-fun s26 () Int (seq.len s24))
-[GOOD] (define-fun s27 () Int (- s26 s13))
-[GOOD] (define-fun s28 () (Seq Int) (seq.extract s24 s13 s27))
-[GOOD] (define-fun s29 () Bool (= s11 s28))
-[GOOD] (define-fun s30 () Int (seq.len s28))
-[GOOD] (define-fun s31 () Int (- s30 s13))
-[GOOD] (define-fun s32 () (Seq Int) (seq.extract s28 s13 s31))
-[GOOD] (define-fun s33 () Bool (= s11 s32))
-[GOOD] (define-fun s34 () Int (seq.len s32))
-[GOOD] (define-fun s35 () Int (- s34 s13))
-[GOOD] (define-fun s36 () (Seq Int) (seq.extract s32 s13 s35))
-[GOOD] (define-fun s37 () Bool (= s11 s36))
-[GOOD] (define-fun s38 () Int (seq.len s36))
-[GOOD] (define-fun s39 () Int (- s38 s13))
-[GOOD] (define-fun s40 () (Seq Int) (seq.extract s36 s13 s39))
-[GOOD] (define-fun s41 () Bool (= s11 s40))
-[GOOD] (define-fun s42 () Int (seq.len s40))
-[GOOD] (define-fun s43 () Int (- s42 s13))
-[GOOD] (define-fun s44 () (Seq Int) (seq.extract s40 s13 s43))
-[GOOD] (define-fun s45 () Bool (= s11 s44))
-[GOOD] (define-fun s46 () Int (seq.len s44))
-[GOOD] (define-fun s47 () Int (- s46 s13))
-[GOOD] (define-fun s48 () (Seq Int) (seq.extract s44 s13 s47))
-[GOOD] (define-fun s49 () Bool (= s11 s48))
-[GOOD] (define-fun s51 () (Seq Int) (seq.unit s50))
-[GOOD] (define-fun s52 () Int (seq.len s48))
-[GOOD] (define-fun s54 () Bool (> s52 s53))
-[GOOD] (define-fun s55 () Bool (not s54))
-[GOOD] (define-fun s56 () (Seq Int) (seq.extract s48 s53 s13))
-[GOOD] (define-fun s57 () Bool (= s51 s56))
-[GOOD] (define-fun s58 () Bool (or s55 s57))
-[GOOD] (define-fun s59 () (Seq Int) (ite s49 s11 s51))
-[GOOD] (define-fun s61 () (Seq Int) (seq.unit s60))
-[GOOD] (define-fun s62 () Bool (> s46 s53))
-[GOOD] (define-fun s63 () Bool (not s62))
-[GOOD] (define-fun s64 () (Seq Int) (seq.extract s44 s53 s13))
-[GOOD] (define-fun s65 () Bool (= s61 s64))
-[GOOD] (define-fun s66 () Bool (or s63 s65))
-[GOOD] (define-fun s67 () (Seq Int) (seq.++ s59 s61))
-[GOOD] (define-fun s68 () (Seq Int) (ite s45 s11 s67))
-[GOOD] (define-fun s70 () (Seq Int) (seq.unit s69))
-[GOOD] (define-fun s71 () Bool (> s42 s53))
-[GOOD] (define-fun s72 () Bool (not s71))
-[GOOD] (define-fun s73 () (Seq Int) (seq.extract s40 s53 s13))
-[GOOD] (define-fun s74 () Bool (= s70 s73))
-[GOOD] (define-fun s75 () Bool (or s72 s74))
-[GOOD] (define-fun s76 () (Seq Int) (seq.++ s68 s70))
-[GOOD] (define-fun s77 () (Seq Int) (ite s41 s11 s76))
-[GOOD] (define-fun s79 () (Seq Int) (seq.unit s78))
-[GOOD] (define-fun s80 () Bool (> s38 s53))
-[GOOD] (define-fun s81 () Bool (not s80))
-[GOOD] (define-fun s82 () (Seq Int) (seq.extract s36 s53 s13))
-[GOOD] (define-fun s83 () Bool (= s79 s82))
-[GOOD] (define-fun s84 () Bool (or s81 s83))
-[GOOD] (define-fun s85 () (Seq Int) (seq.++ s77 s79))
-[GOOD] (define-fun s86 () (Seq Int) (ite s37 s11 s85))
-[GOOD] (define-fun s88 () (Seq Int) (seq.unit s87))
-[GOOD] (define-fun s89 () Bool (> s34 s53))
-[GOOD] (define-fun s90 () Bool (not s89))
-[GOOD] (define-fun s91 () (Seq Int) (seq.extract s32 s53 s13))
-[GOOD] (define-fun s92 () Bool (= s88 s91))
-[GOOD] (define-fun s93 () Bool (or s90 s92))
-[GOOD] (define-fun s94 () (Seq Int) (seq.++ s86 s88))
-[GOOD] (define-fun s95 () (Seq Int) (ite s33 s11 s94))
-[GOOD] (define-fun s97 () (Seq Int) (seq.unit s96))
-[GOOD] (define-fun s98 () Bool (> s30 s53))
-[GOOD] (define-fun s99 () Bool (not s98))
-[GOOD] (define-fun s100 () (Seq Int) (seq.extract s28 s53 s13))
-[GOOD] (define-fun s101 () Bool (= s97 s100))
-[GOOD] (define-fun s102 () Bool (or s99 s101))
-[GOOD] (define-fun s103 () (Seq Int) (seq.++ s95 s97))
-[GOOD] (define-fun s104 () (Seq Int) (ite s29 s11 s103))
-[GOOD] (define-fun s106 () (Seq Int) (seq.unit s105))
-[GOOD] (define-fun s107 () Bool (> s26 s53))
-[GOOD] (define-fun s108 () Bool (not s107))
-[GOOD] (define-fun s109 () (Seq Int) (seq.extract s24 s53 s13))
-[GOOD] (define-fun s110 () Bool (= s106 s109))
-[GOOD] (define-fun s111 () Bool (or s108 s110))
-[GOOD] (define-fun s112 () (Seq Int) (seq.++ s104 s106))
-[GOOD] (define-fun s113 () (Seq Int) (ite s25 s11 s112))
-[GOOD] (define-fun s115 () (Seq Int) (seq.unit s114))
-[GOOD] (define-fun s116 () Bool (> s22 s53))
-[GOOD] (define-fun s117 () Bool (not s116))
-[GOOD] (define-fun s118 () (Seq Int) (seq.extract s20 s53 s13))
-[GOOD] (define-fun s119 () Bool (= s115 s118))
-[GOOD] (define-fun s120 () Bool (or s117 s119))
-[GOOD] (define-fun s121 () (Seq Int) (seq.++ s113 s115))
-[GOOD] (define-fun s122 () (Seq Int) (ite s21 s11 s121))
+[GOOD] (define-fun s11 () Int (seq.len s10))
+[GOOD] (define-fun s13 () Bool (= s11 s12))
+[GOOD] (define-fun s16 () Int (- s11 s15))
+[GOOD] (define-fun s17 () (Seq Int) (seq.extract s10 s15 s16))
+[GOOD] (define-fun s18 () Int (seq.len s17))
+[GOOD] (define-fun s19 () Bool (= s12 s18))
+[GOOD] (define-fun s20 () Int (- s18 s15))
+[GOOD] (define-fun s21 () (Seq Int) (seq.extract s17 s15 s20))
+[GOOD] (define-fun s22 () Int (seq.len s21))
+[GOOD] (define-fun s23 () Bool (= s12 s22))
+[GOOD] (define-fun s24 () Int (- s22 s15))
+[GOOD] (define-fun s25 () (Seq Int) (seq.extract s21 s15 s24))
+[GOOD] (define-fun s26 () Int (seq.len s25))
+[GOOD] (define-fun s27 () Bool (= s12 s26))
+[GOOD] (define-fun s28 () Int (- s26 s15))
+[GOOD] (define-fun s29 () (Seq Int) (seq.extract s25 s15 s28))
+[GOOD] (define-fun s30 () Int (seq.len s29))
+[GOOD] (define-fun s31 () Bool (= s12 s30))
+[GOOD] (define-fun s32 () Int (- s30 s15))
+[GOOD] (define-fun s33 () (Seq Int) (seq.extract s29 s15 s32))
+[GOOD] (define-fun s34 () Int (seq.len s33))
+[GOOD] (define-fun s35 () Bool (= s12 s34))
+[GOOD] (define-fun s36 () Int (- s34 s15))
+[GOOD] (define-fun s37 () (Seq Int) (seq.extract s33 s15 s36))
+[GOOD] (define-fun s38 () Int (seq.len s37))
+[GOOD] (define-fun s39 () Bool (= s12 s38))
+[GOOD] (define-fun s40 () Int (- s38 s15))
+[GOOD] (define-fun s41 () (Seq Int) (seq.extract s37 s15 s40))
+[GOOD] (define-fun s42 () Int (seq.len s41))
+[GOOD] (define-fun s43 () Bool (= s12 s42))
+[GOOD] (define-fun s44 () Int (- s42 s15))
+[GOOD] (define-fun s45 () (Seq Int) (seq.extract s41 s15 s44))
+[GOOD] (define-fun s46 () Int (seq.len s45))
+[GOOD] (define-fun s47 () Bool (= s12 s46))
+[GOOD] (define-fun s48 () Int (- s46 s15))
+[GOOD] (define-fun s49 () (Seq Int) (seq.extract s45 s15 s48))
+[GOOD] (define-fun s50 () Int (seq.len s49))
+[GOOD] (define-fun s51 () Bool (= s12 s50))
+[GOOD] (define-fun s53 () (Seq Int) (seq.unit s52))
+[GOOD] (define-fun s54 () (Seq Int) (seq.extract s49 s12 s15))
+[GOOD] (define-fun s55 () Bool (= s53 s54))
+[GOOD] (define-fun s56 () Bool (<= s50 s12))
+[GOOD] (define-fun s57 () Bool (or s55 s56))
+[GOOD] (define-fun s58 () (Seq Int) (ite s51 s14 s53))
+[GOOD] (define-fun s60 () (Seq Int) (seq.unit s59))
+[GOOD] (define-fun s61 () (Seq Int) (seq.extract s45 s12 s15))
+[GOOD] (define-fun s62 () Bool (= s60 s61))
+[GOOD] (define-fun s63 () Bool (<= s46 s12))
+[GOOD] (define-fun s64 () Bool (or s62 s63))
+[GOOD] (define-fun s65 () (Seq Int) (seq.++ s58 s60))
+[GOOD] (define-fun s66 () (Seq Int) (ite s47 s14 s65))
+[GOOD] (define-fun s68 () (Seq Int) (seq.unit s67))
+[GOOD] (define-fun s69 () (Seq Int) (seq.extract s41 s12 s15))
+[GOOD] (define-fun s70 () Bool (= s68 s69))
+[GOOD] (define-fun s71 () Bool (<= s42 s12))
+[GOOD] (define-fun s72 () Bool (or s70 s71))
+[GOOD] (define-fun s73 () (Seq Int) (seq.++ s66 s68))
+[GOOD] (define-fun s74 () (Seq Int) (ite s43 s14 s73))
+[GOOD] (define-fun s76 () (Seq Int) (seq.unit s75))
+[GOOD] (define-fun s77 () (Seq Int) (seq.extract s37 s12 s15))
+[GOOD] (define-fun s78 () Bool (= s76 s77))
+[GOOD] (define-fun s79 () Bool (<= s38 s12))
+[GOOD] (define-fun s80 () Bool (or s78 s79))
+[GOOD] (define-fun s81 () (Seq Int) (seq.++ s74 s76))
+[GOOD] (define-fun s82 () (Seq Int) (ite s39 s14 s81))
+[GOOD] (define-fun s84 () (Seq Int) (seq.unit s83))
+[GOOD] (define-fun s85 () (Seq Int) (seq.extract s33 s12 s15))
+[GOOD] (define-fun s86 () Bool (= s84 s85))
+[GOOD] (define-fun s87 () Bool (<= s34 s12))
+[GOOD] (define-fun s88 () Bool (or s86 s87))
+[GOOD] (define-fun s89 () (Seq Int) (seq.++ s82 s84))
+[GOOD] (define-fun s90 () (Seq Int) (ite s35 s14 s89))
+[GOOD] (define-fun s92 () (Seq Int) (seq.unit s91))
+[GOOD] (define-fun s93 () (Seq Int) (seq.extract s29 s12 s15))
+[GOOD] (define-fun s94 () Bool (= s92 s93))
+[GOOD] (define-fun s95 () Bool (<= s30 s12))
+[GOOD] (define-fun s96 () Bool (or s94 s95))
+[GOOD] (define-fun s97 () (Seq Int) (seq.++ s90 s92))
+[GOOD] (define-fun s98 () (Seq Int) (ite s31 s14 s97))
+[GOOD] (define-fun s100 () (Seq Int) (seq.unit s99))
+[GOOD] (define-fun s101 () (Seq Int) (seq.extract s25 s12 s15))
+[GOOD] (define-fun s102 () Bool (= s100 s101))
+[GOOD] (define-fun s103 () Bool (<= s26 s12))
+[GOOD] (define-fun s104 () Bool (or s102 s103))
+[GOOD] (define-fun s105 () (Seq Int) (seq.++ s98 s100))
+[GOOD] (define-fun s106 () (Seq Int) (ite s27 s14 s105))
+[GOOD] (define-fun s108 () (Seq Int) (seq.unit s107))
+[GOOD] (define-fun s109 () (Seq Int) (seq.extract s21 s12 s15))
+[GOOD] (define-fun s110 () Bool (= s108 s109))
+[GOOD] (define-fun s111 () Bool (<= s22 s12))
+[GOOD] (define-fun s112 () Bool (or s110 s111))
+[GOOD] (define-fun s113 () (Seq Int) (seq.++ s106 s108))
+[GOOD] (define-fun s114 () (Seq Int) (ite s23 s14 s113))
+[GOOD] (define-fun s116 () (Seq Int) (seq.unit s115))
+[GOOD] (define-fun s117 () (Seq Int) (seq.extract s17 s12 s15))
+[GOOD] (define-fun s118 () Bool (= s116 s117))
+[GOOD] (define-fun s119 () Bool (<= s18 s12))
+[GOOD] (define-fun s120 () Bool (or s118 s119))
+[GOOD] (define-fun s121 () (Seq Int) (seq.++ s114 s116))
+[GOOD] (define-fun s122 () (Seq Int) (ite s19 s14 s121))
 [GOOD] (define-fun s124 () (Seq Int) (seq.unit s123))
-[GOOD] (define-fun s125 () Bool (> s18 s53))
-[GOOD] (define-fun s126 () Bool (not s125))
-[GOOD] (define-fun s127 () (Seq Int) (seq.extract s16 s53 s13))
-[GOOD] (define-fun s128 () Bool (= s124 s127))
-[GOOD] (define-fun s129 () Bool (or s126 s128))
-[GOOD] (define-fun s130 () (Seq Int) (seq.++ s122 s124))
-[GOOD] (define-fun s131 () (Seq Int) (ite s17 s11 s130))
-[GOOD] (define-fun s133 () (Seq Int) (seq.unit s132))
-[GOOD] (define-fun s134 () Bool (> s14 s53))
-[GOOD] (define-fun s135 () Bool (not s134))
-[GOOD] (define-fun s136 () (Seq Int) (seq.extract s10 s53 s13))
-[GOOD] (define-fun s137 () Bool (= s133 s136))
-[GOOD] (define-fun s138 () Bool (or s135 s137))
-[GOOD] (define-fun s139 () (Seq Int) (seq.++ s131 s133))
-[GOOD] (define-fun s140 () (Seq Int) (ite s12 s11 s139))
-[GOOD] (define-fun s141 () (Seq Int) (seq.++ s5 s4))
-[GOOD] (define-fun s142 () (Seq Int) (seq.++ s6 s141))
-[GOOD] (define-fun s143 () (Seq Int) (seq.++ s7 s142))
-[GOOD] (define-fun s144 () Bool (= s140 s143))
-[GOOD] (assert s58)
-[GOOD] (assert s66)
-[GOOD] (assert s75)
-[GOOD] (assert s84)
-[GOOD] (assert s93)
-[GOOD] (assert s102)
-[GOOD] (assert s111)
+[GOOD] (define-fun s125 () (Seq Int) (seq.extract s10 s12 s15))
+[GOOD] (define-fun s126 () Bool (= s124 s125))
+[GOOD] (define-fun s127 () Bool (<= s11 s12))
+[GOOD] (define-fun s128 () Bool (or s126 s127))
+[GOOD] (define-fun s129 () (Seq Int) (seq.++ s122 s124))
+[GOOD] (define-fun s130 () (Seq Int) (ite s13 s14 s129))
+[GOOD] (define-fun s131 () (Seq Int) (seq.++ s5 s4))
+[GOOD] (define-fun s132 () (Seq Int) (seq.++ s6 s131))
+[GOOD] (define-fun s133 () (Seq Int) (seq.++ s7 s132))
+[GOOD] (define-fun s134 () Bool (= s130 s133))
+[GOOD] (assert s57)
+[GOOD] (assert s64)
+[GOOD] (assert s72)
+[GOOD] (assert s80)
+[GOOD] (assert s88)
+[GOOD] (assert s96)
+[GOOD] (assert s104)
+[GOOD] (assert s112)
 [GOOD] (assert s120)
-[GOOD] (assert s129)
-[GOOD] (assert s138)
-[GOOD] (assert s144)
+[GOOD] (assert s128)
+[GOOD] (assert s134)
 [SEND] (check-sat)
 [RECV] sat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/reverseAlt10.gold b/SBVTestSuite/GoldFiles/reverseAlt10.gold
--- a/SBVTestSuite/GoldFiles/reverseAlt10.gold
+++ b/SBVTestSuite/GoldFiles/reverseAlt10.gold
@@ -10,23 +10,26 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s3 () Int 1)
-[GOOD] (define-fun s43 () Int 0)
-[GOOD] (define-fun s1 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] (define-fun s5 () Int 1)
+[GOOD] (define-fun s4 () (Seq Int) (as seq.empty (Seq Int)))
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "xs"
-[GOOD] (declare-fun s40 () Int) ; tracks user variable "__internal_sbv_s40"
-[GOOD] (declare-fun s50 () Int) ; tracks user variable "__internal_sbv_s50"
-[GOOD] (declare-fun s59 () Int) ; tracks user variable "__internal_sbv_s59"
-[GOOD] (declare-fun s68 () Int) ; tracks user variable "__internal_sbv_s68"
-[GOOD] (declare-fun s77 () Int) ; tracks user variable "__internal_sbv_s77"
-[GOOD] (declare-fun s86 () Int) ; tracks user variable "__internal_sbv_s86"
-[GOOD] (declare-fun s95 () Int) ; tracks user variable "__internal_sbv_s95"
-[GOOD] (declare-fun s104 () Int) ; tracks user variable "__internal_sbv_s104"
+[GOOD] (declare-fun s42 () Int) ; tracks user variable "__internal_sbv_s42"
+[GOOD] (declare-fun s49 () Int) ; tracks user variable "__internal_sbv_s49"
+[GOOD] (declare-fun s57 () Int) ; tracks user variable "__internal_sbv_s57"
+[GOOD] (declare-fun s65 () Int) ; tracks user variable "__internal_sbv_s65"
+[GOOD] (declare-fun s73 () Int) ; tracks user variable "__internal_sbv_s73"
+[GOOD] (declare-fun s81 () Int) ; tracks user variable "__internal_sbv_s81"
+[GOOD] (declare-fun s89 () Int) ; tracks user variable "__internal_sbv_s89"
+[GOOD] (declare-fun s97 () Int) ; tracks user variable "__internal_sbv_s97"
+[GOOD] (declare-fun s105 () Int) ; tracks user variable "__internal_sbv_s105"
 [GOOD] (declare-fun s113 () Int) ; tracks user variable "__internal_sbv_s113"
-[GOOD] (declare-fun s122 () Int) ; tracks user variable "__internal_sbv_s122"
-[GOOD] (declare-fun s131 () Int) ; tracks user variable "__internal_sbv_s131"
+[GOOD] (declare-fun s121 () Int) ; tracks user variable "__internal_sbv_s121"
+[GOOD] (declare-fun s125 () Int) ; tracks user variable "__internal_sbv_s125"
+[GOOD] (declare-fun s130 () Int) ; tracks user variable "__internal_sbv_s130"
 [GOOD] (declare-fun s135 () Int) ; tracks user variable "__internal_sbv_s135"
 [GOOD] (declare-fun s140 () Int) ; tracks user variable "__internal_sbv_s140"
 [GOOD] (declare-fun s145 () Int) ; tracks user variable "__internal_sbv_s145"
@@ -34,192 +37,182 @@
 [GOOD] (declare-fun s155 () Int) ; tracks user variable "__internal_sbv_s155"
 [GOOD] (declare-fun s160 () Int) ; tracks user variable "__internal_sbv_s160"
 [GOOD] (declare-fun s165 () Int) ; tracks user variable "__internal_sbv_s165"
-[GOOD] (declare-fun s170 () Int) ; tracks user variable "__internal_sbv_s170"
-[GOOD] (declare-fun s175 () Int) ; tracks user variable "__internal_sbv_s175"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
 [GOOD] ; --- uninterpreted constants ---
 [GOOD] ; --- user given axioms ---
 [GOOD] ; --- formula ---
-[GOOD] (define-fun s2 () Bool (= s0 s1))
-[GOOD] (define-fun s4 () Int (seq.len s0))
-[GOOD] (define-fun s5 () Int (- s4 s3))
-[GOOD] (define-fun s6 () (Seq Int) (seq.extract s0 s3 s5))
-[GOOD] (define-fun s7 () Bool (= s1 s6))
-[GOOD] (define-fun s8 () Int (seq.len s6))
-[GOOD] (define-fun s9 () Int (- s8 s3))
-[GOOD] (define-fun s10 () (Seq Int) (seq.extract s6 s3 s9))
-[GOOD] (define-fun s11 () Bool (= s1 s10))
-[GOOD] (define-fun s12 () Int (seq.len s10))
-[GOOD] (define-fun s13 () Int (- s12 s3))
-[GOOD] (define-fun s14 () (Seq Int) (seq.extract s10 s3 s13))
-[GOOD] (define-fun s15 () Bool (= s1 s14))
-[GOOD] (define-fun s16 () Int (seq.len s14))
-[GOOD] (define-fun s17 () Int (- s16 s3))
-[GOOD] (define-fun s18 () (Seq Int) (seq.extract s14 s3 s17))
-[GOOD] (define-fun s19 () Bool (= s1 s18))
-[GOOD] (define-fun s20 () Int (seq.len s18))
-[GOOD] (define-fun s21 () Int (- s20 s3))
-[GOOD] (define-fun s22 () (Seq Int) (seq.extract s18 s3 s21))
-[GOOD] (define-fun s23 () Bool (= s1 s22))
-[GOOD] (define-fun s24 () Int (seq.len s22))
-[GOOD] (define-fun s25 () Int (- s24 s3))
-[GOOD] (define-fun s26 () (Seq Int) (seq.extract s22 s3 s25))
-[GOOD] (define-fun s27 () Bool (= s1 s26))
-[GOOD] (define-fun s28 () Int (seq.len s26))
-[GOOD] (define-fun s29 () Int (- s28 s3))
-[GOOD] (define-fun s30 () (Seq Int) (seq.extract s26 s3 s29))
-[GOOD] (define-fun s31 () Bool (= s1 s30))
-[GOOD] (define-fun s32 () Int (seq.len s30))
-[GOOD] (define-fun s33 () Int (- s32 s3))
-[GOOD] (define-fun s34 () (Seq Int) (seq.extract s30 s3 s33))
-[GOOD] (define-fun s35 () Bool (= s1 s34))
-[GOOD] (define-fun s36 () Int (seq.len s34))
-[GOOD] (define-fun s37 () Int (- s36 s3))
-[GOOD] (define-fun s38 () (Seq Int) (seq.extract s34 s3 s37))
-[GOOD] (define-fun s39 () Bool (= s1 s38))
-[GOOD] (define-fun s41 () (Seq Int) (seq.unit s40))
-[GOOD] (define-fun s42 () Int (seq.len s38))
-[GOOD] (define-fun s44 () Bool (> s42 s43))
-[GOOD] (define-fun s45 () Bool (not s44))
-[GOOD] (define-fun s46 () (Seq Int) (seq.extract s38 s43 s3))
-[GOOD] (define-fun s47 () Bool (= s41 s46))
-[GOOD] (define-fun s48 () Bool (or s45 s47))
-[GOOD] (define-fun s49 () (Seq Int) (ite s39 s1 s41))
-[GOOD] (define-fun s51 () (Seq Int) (seq.unit s50))
-[GOOD] (define-fun s52 () Bool (> s36 s43))
-[GOOD] (define-fun s53 () Bool (not s52))
-[GOOD] (define-fun s54 () (Seq Int) (seq.extract s34 s43 s3))
-[GOOD] (define-fun s55 () Bool (= s51 s54))
-[GOOD] (define-fun s56 () Bool (or s53 s55))
-[GOOD] (define-fun s57 () (Seq Int) (seq.++ s49 s51))
-[GOOD] (define-fun s58 () (Seq Int) (ite s35 s1 s57))
-[GOOD] (define-fun s60 () (Seq Int) (seq.unit s59))
-[GOOD] (define-fun s61 () Bool (> s32 s43))
-[GOOD] (define-fun s62 () Bool (not s61))
-[GOOD] (define-fun s63 () (Seq Int) (seq.extract s30 s43 s3))
-[GOOD] (define-fun s64 () Bool (= s60 s63))
-[GOOD] (define-fun s65 () Bool (or s62 s64))
-[GOOD] (define-fun s66 () (Seq Int) (seq.++ s58 s60))
-[GOOD] (define-fun s67 () (Seq Int) (ite s31 s1 s66))
-[GOOD] (define-fun s69 () (Seq Int) (seq.unit s68))
-[GOOD] (define-fun s70 () Bool (> s28 s43))
-[GOOD] (define-fun s71 () Bool (not s70))
-[GOOD] (define-fun s72 () (Seq Int) (seq.extract s26 s43 s3))
-[GOOD] (define-fun s73 () Bool (= s69 s72))
-[GOOD] (define-fun s74 () Bool (or s71 s73))
-[GOOD] (define-fun s75 () (Seq Int) (seq.++ s67 s69))
-[GOOD] (define-fun s76 () (Seq Int) (ite s27 s1 s75))
-[GOOD] (define-fun s78 () (Seq Int) (seq.unit s77))
-[GOOD] (define-fun s79 () Bool (> s24 s43))
-[GOOD] (define-fun s80 () Bool (not s79))
-[GOOD] (define-fun s81 () (Seq Int) (seq.extract s22 s43 s3))
-[GOOD] (define-fun s82 () Bool (= s78 s81))
-[GOOD] (define-fun s83 () Bool (or s80 s82))
-[GOOD] (define-fun s84 () (Seq Int) (seq.++ s76 s78))
-[GOOD] (define-fun s85 () (Seq Int) (ite s23 s1 s84))
-[GOOD] (define-fun s87 () (Seq Int) (seq.unit s86))
-[GOOD] (define-fun s88 () Bool (> s20 s43))
-[GOOD] (define-fun s89 () Bool (not s88))
-[GOOD] (define-fun s90 () (Seq Int) (seq.extract s18 s43 s3))
-[GOOD] (define-fun s91 () Bool (= s87 s90))
-[GOOD] (define-fun s92 () Bool (or s89 s91))
-[GOOD] (define-fun s93 () (Seq Int) (seq.++ s85 s87))
-[GOOD] (define-fun s94 () (Seq Int) (ite s19 s1 s93))
-[GOOD] (define-fun s96 () (Seq Int) (seq.unit s95))
-[GOOD] (define-fun s97 () Bool (> s16 s43))
-[GOOD] (define-fun s98 () Bool (not s97))
-[GOOD] (define-fun s99 () (Seq Int) (seq.extract s14 s43 s3))
-[GOOD] (define-fun s100 () Bool (= s96 s99))
-[GOOD] (define-fun s101 () Bool (or s98 s100))
-[GOOD] (define-fun s102 () (Seq Int) (seq.++ s94 s96))
-[GOOD] (define-fun s103 () (Seq Int) (ite s15 s1 s102))
-[GOOD] (define-fun s105 () (Seq Int) (seq.unit s104))
-[GOOD] (define-fun s106 () Bool (> s12 s43))
-[GOOD] (define-fun s107 () Bool (not s106))
-[GOOD] (define-fun s108 () (Seq Int) (seq.extract s10 s43 s3))
-[GOOD] (define-fun s109 () Bool (= s105 s108))
-[GOOD] (define-fun s110 () Bool (or s107 s109))
-[GOOD] (define-fun s111 () (Seq Int) (seq.++ s103 s105))
-[GOOD] (define-fun s112 () (Seq Int) (ite s11 s1 s111))
+[GOOD] (define-fun s1 () Int (seq.len s0))
+[GOOD] (define-fun s3 () Bool (= s1 s2))
+[GOOD] (define-fun s6 () Int (- s1 s5))
+[GOOD] (define-fun s7 () (Seq Int) (seq.extract s0 s5 s6))
+[GOOD] (define-fun s8 () Int (seq.len s7))
+[GOOD] (define-fun s9 () Bool (= s2 s8))
+[GOOD] (define-fun s10 () Int (- s8 s5))
+[GOOD] (define-fun s11 () (Seq Int) (seq.extract s7 s5 s10))
+[GOOD] (define-fun s12 () Int (seq.len s11))
+[GOOD] (define-fun s13 () Bool (= s2 s12))
+[GOOD] (define-fun s14 () Int (- s12 s5))
+[GOOD] (define-fun s15 () (Seq Int) (seq.extract s11 s5 s14))
+[GOOD] (define-fun s16 () Int (seq.len s15))
+[GOOD] (define-fun s17 () Bool (= s2 s16))
+[GOOD] (define-fun s18 () Int (- s16 s5))
+[GOOD] (define-fun s19 () (Seq Int) (seq.extract s15 s5 s18))
+[GOOD] (define-fun s20 () Int (seq.len s19))
+[GOOD] (define-fun s21 () Bool (= s2 s20))
+[GOOD] (define-fun s22 () Int (- s20 s5))
+[GOOD] (define-fun s23 () (Seq Int) (seq.extract s19 s5 s22))
+[GOOD] (define-fun s24 () Int (seq.len s23))
+[GOOD] (define-fun s25 () Bool (= s2 s24))
+[GOOD] (define-fun s26 () Int (- s24 s5))
+[GOOD] (define-fun s27 () (Seq Int) (seq.extract s23 s5 s26))
+[GOOD] (define-fun s28 () Int (seq.len s27))
+[GOOD] (define-fun s29 () Bool (= s2 s28))
+[GOOD] (define-fun s30 () Int (- s28 s5))
+[GOOD] (define-fun s31 () (Seq Int) (seq.extract s27 s5 s30))
+[GOOD] (define-fun s32 () Int (seq.len s31))
+[GOOD] (define-fun s33 () Bool (= s2 s32))
+[GOOD] (define-fun s34 () Int (- s32 s5))
+[GOOD] (define-fun s35 () (Seq Int) (seq.extract s31 s5 s34))
+[GOOD] (define-fun s36 () Int (seq.len s35))
+[GOOD] (define-fun s37 () Bool (= s2 s36))
+[GOOD] (define-fun s38 () Int (- s36 s5))
+[GOOD] (define-fun s39 () (Seq Int) (seq.extract s35 s5 s38))
+[GOOD] (define-fun s40 () Int (seq.len s39))
+[GOOD] (define-fun s41 () Bool (= s2 s40))
+[GOOD] (define-fun s43 () (Seq Int) (seq.unit s42))
+[GOOD] (define-fun s44 () (Seq Int) (seq.extract s39 s2 s5))
+[GOOD] (define-fun s45 () Bool (= s43 s44))
+[GOOD] (define-fun s46 () Bool (<= s40 s2))
+[GOOD] (define-fun s47 () Bool (or s45 s46))
+[GOOD] (define-fun s48 () (Seq Int) (ite s41 s4 s43))
+[GOOD] (define-fun s50 () (Seq Int) (seq.unit s49))
+[GOOD] (define-fun s51 () (Seq Int) (seq.extract s35 s2 s5))
+[GOOD] (define-fun s52 () Bool (= s50 s51))
+[GOOD] (define-fun s53 () Bool (<= s36 s2))
+[GOOD] (define-fun s54 () Bool (or s52 s53))
+[GOOD] (define-fun s55 () (Seq Int) (seq.++ s48 s50))
+[GOOD] (define-fun s56 () (Seq Int) (ite s37 s4 s55))
+[GOOD] (define-fun s58 () (Seq Int) (seq.unit s57))
+[GOOD] (define-fun s59 () (Seq Int) (seq.extract s31 s2 s5))
+[GOOD] (define-fun s60 () Bool (= s58 s59))
+[GOOD] (define-fun s61 () Bool (<= s32 s2))
+[GOOD] (define-fun s62 () Bool (or s60 s61))
+[GOOD] (define-fun s63 () (Seq Int) (seq.++ s56 s58))
+[GOOD] (define-fun s64 () (Seq Int) (ite s33 s4 s63))
+[GOOD] (define-fun s66 () (Seq Int) (seq.unit s65))
+[GOOD] (define-fun s67 () (Seq Int) (seq.extract s27 s2 s5))
+[GOOD] (define-fun s68 () Bool (= s66 s67))
+[GOOD] (define-fun s69 () Bool (<= s28 s2))
+[GOOD] (define-fun s70 () Bool (or s68 s69))
+[GOOD] (define-fun s71 () (Seq Int) (seq.++ s64 s66))
+[GOOD] (define-fun s72 () (Seq Int) (ite s29 s4 s71))
+[GOOD] (define-fun s74 () (Seq Int) (seq.unit s73))
+[GOOD] (define-fun s75 () (Seq Int) (seq.extract s23 s2 s5))
+[GOOD] (define-fun s76 () Bool (= s74 s75))
+[GOOD] (define-fun s77 () Bool (<= s24 s2))
+[GOOD] (define-fun s78 () Bool (or s76 s77))
+[GOOD] (define-fun s79 () (Seq Int) (seq.++ s72 s74))
+[GOOD] (define-fun s80 () (Seq Int) (ite s25 s4 s79))
+[GOOD] (define-fun s82 () (Seq Int) (seq.unit s81))
+[GOOD] (define-fun s83 () (Seq Int) (seq.extract s19 s2 s5))
+[GOOD] (define-fun s84 () Bool (= s82 s83))
+[GOOD] (define-fun s85 () Bool (<= s20 s2))
+[GOOD] (define-fun s86 () Bool (or s84 s85))
+[GOOD] (define-fun s87 () (Seq Int) (seq.++ s80 s82))
+[GOOD] (define-fun s88 () (Seq Int) (ite s21 s4 s87))
+[GOOD] (define-fun s90 () (Seq Int) (seq.unit s89))
+[GOOD] (define-fun s91 () (Seq Int) (seq.extract s15 s2 s5))
+[GOOD] (define-fun s92 () Bool (= s90 s91))
+[GOOD] (define-fun s93 () Bool (<= s16 s2))
+[GOOD] (define-fun s94 () Bool (or s92 s93))
+[GOOD] (define-fun s95 () (Seq Int) (seq.++ s88 s90))
+[GOOD] (define-fun s96 () (Seq Int) (ite s17 s4 s95))
+[GOOD] (define-fun s98 () (Seq Int) (seq.unit s97))
+[GOOD] (define-fun s99 () (Seq Int) (seq.extract s11 s2 s5))
+[GOOD] (define-fun s100 () Bool (= s98 s99))
+[GOOD] (define-fun s101 () Bool (<= s12 s2))
+[GOOD] (define-fun s102 () Bool (or s100 s101))
+[GOOD] (define-fun s103 () (Seq Int) (seq.++ s96 s98))
+[GOOD] (define-fun s104 () (Seq Int) (ite s13 s4 s103))
+[GOOD] (define-fun s106 () (Seq Int) (seq.unit s105))
+[GOOD] (define-fun s107 () (Seq Int) (seq.extract s7 s2 s5))
+[GOOD] (define-fun s108 () Bool (= s106 s107))
+[GOOD] (define-fun s109 () Bool (<= s8 s2))
+[GOOD] (define-fun s110 () Bool (or s108 s109))
+[GOOD] (define-fun s111 () (Seq Int) (seq.++ s104 s106))
+[GOOD] (define-fun s112 () (Seq Int) (ite s9 s4 s111))
 [GOOD] (define-fun s114 () (Seq Int) (seq.unit s113))
-[GOOD] (define-fun s115 () Bool (> s8 s43))
-[GOOD] (define-fun s116 () Bool (not s115))
-[GOOD] (define-fun s117 () (Seq Int) (seq.extract s6 s43 s3))
-[GOOD] (define-fun s118 () Bool (= s114 s117))
-[GOOD] (define-fun s119 () Bool (or s116 s118))
-[GOOD] (define-fun s120 () (Seq Int) (seq.++ s112 s114))
-[GOOD] (define-fun s121 () (Seq Int) (ite s7 s1 s120))
-[GOOD] (define-fun s123 () (Seq Int) (seq.unit s122))
-[GOOD] (define-fun s124 () Bool (> s4 s43))
-[GOOD] (define-fun s125 () Bool (not s124))
-[GOOD] (define-fun s126 () (Seq Int) (seq.extract s0 s43 s3))
-[GOOD] (define-fun s127 () Bool (= s123 s126))
-[GOOD] (define-fun s128 () Bool (or s125 s127))
-[GOOD] (define-fun s129 () (Seq Int) (seq.++ s121 s123))
-[GOOD] (define-fun s130 () (Seq Int) (ite s2 s1 s129))
-[GOOD] (define-fun s132 () (Seq Int) (seq.unit s131))
-[GOOD] (define-fun s133 () Bool (= s126 s132))
-[GOOD] (define-fun s134 () Bool (or s125 s133))
+[GOOD] (define-fun s115 () (Seq Int) (seq.extract s0 s2 s5))
+[GOOD] (define-fun s116 () Bool (= s114 s115))
+[GOOD] (define-fun s117 () Bool (<= s1 s2))
+[GOOD] (define-fun s118 () Bool (or s116 s117))
+[GOOD] (define-fun s119 () (Seq Int) (seq.++ s112 s114))
+[GOOD] (define-fun s120 () (Seq Int) (ite s3 s4 s119))
+[GOOD] (define-fun s122 () (Seq Int) (seq.unit s121))
+[GOOD] (define-fun s123 () Bool (= s115 s122))
+[GOOD] (define-fun s124 () Bool (or s117 s123))
+[GOOD] (define-fun s126 () (Seq Int) (seq.unit s125))
+[GOOD] (define-fun s127 () Bool (= s107 s126))
+[GOOD] (define-fun s128 () Bool (or s109 s127))
+[GOOD] (define-fun s129 () (Seq Int) (seq.++ s126 s122))
+[GOOD] (define-fun s131 () (Seq Int) (seq.unit s130))
+[GOOD] (define-fun s132 () Bool (= s99 s131))
+[GOOD] (define-fun s133 () Bool (or s101 s132))
+[GOOD] (define-fun s134 () (Seq Int) (seq.++ s131 s129))
 [GOOD] (define-fun s136 () (Seq Int) (seq.unit s135))
-[GOOD] (define-fun s137 () Bool (= s117 s136))
-[GOOD] (define-fun s138 () Bool (or s116 s137))
-[GOOD] (define-fun s139 () (Seq Int) (seq.++ s136 s132))
+[GOOD] (define-fun s137 () Bool (= s91 s136))
+[GOOD] (define-fun s138 () Bool (or s93 s137))
+[GOOD] (define-fun s139 () (Seq Int) (seq.++ s136 s134))
 [GOOD] (define-fun s141 () (Seq Int) (seq.unit s140))
-[GOOD] (define-fun s142 () Bool (= s108 s141))
-[GOOD] (define-fun s143 () Bool (or s107 s142))
+[GOOD] (define-fun s142 () Bool (= s83 s141))
+[GOOD] (define-fun s143 () Bool (or s85 s142))
 [GOOD] (define-fun s144 () (Seq Int) (seq.++ s141 s139))
 [GOOD] (define-fun s146 () (Seq Int) (seq.unit s145))
-[GOOD] (define-fun s147 () Bool (= s99 s146))
-[GOOD] (define-fun s148 () Bool (or s98 s147))
+[GOOD] (define-fun s147 () Bool (= s75 s146))
+[GOOD] (define-fun s148 () Bool (or s77 s147))
 [GOOD] (define-fun s149 () (Seq Int) (seq.++ s146 s144))
 [GOOD] (define-fun s151 () (Seq Int) (seq.unit s150))
-[GOOD] (define-fun s152 () Bool (= s90 s151))
-[GOOD] (define-fun s153 () Bool (or s89 s152))
+[GOOD] (define-fun s152 () Bool (= s67 s151))
+[GOOD] (define-fun s153 () Bool (or s69 s152))
 [GOOD] (define-fun s154 () (Seq Int) (seq.++ s151 s149))
 [GOOD] (define-fun s156 () (Seq Int) (seq.unit s155))
-[GOOD] (define-fun s157 () Bool (= s81 s156))
-[GOOD] (define-fun s158 () Bool (or s80 s157))
+[GOOD] (define-fun s157 () Bool (= s59 s156))
+[GOOD] (define-fun s158 () Bool (or s61 s157))
 [GOOD] (define-fun s159 () (Seq Int) (seq.++ s156 s154))
 [GOOD] (define-fun s161 () (Seq Int) (seq.unit s160))
-[GOOD] (define-fun s162 () Bool (= s72 s161))
-[GOOD] (define-fun s163 () Bool (or s71 s162))
+[GOOD] (define-fun s162 () Bool (= s51 s161))
+[GOOD] (define-fun s163 () Bool (or s53 s162))
 [GOOD] (define-fun s164 () (Seq Int) (seq.++ s161 s159))
 [GOOD] (define-fun s166 () (Seq Int) (seq.unit s165))
-[GOOD] (define-fun s167 () Bool (= s63 s166))
-[GOOD] (define-fun s168 () Bool (or s62 s167))
+[GOOD] (define-fun s167 () Bool (= s44 s166))
+[GOOD] (define-fun s168 () Bool (or s46 s167))
 [GOOD] (define-fun s169 () (Seq Int) (seq.++ s166 s164))
-[GOOD] (define-fun s171 () (Seq Int) (seq.unit s170))
-[GOOD] (define-fun s172 () Bool (= s54 s171))
-[GOOD] (define-fun s173 () Bool (or s53 s172))
-[GOOD] (define-fun s174 () (Seq Int) (seq.++ s171 s169))
-[GOOD] (define-fun s176 () (Seq Int) (seq.unit s175))
-[GOOD] (define-fun s177 () Bool (= s46 s176))
-[GOOD] (define-fun s178 () Bool (or s45 s177))
-[GOOD] (define-fun s179 () (Seq Int) (seq.++ s176 s174))
-[GOOD] (define-fun s180 () (Seq Int) (ite s39 s174 s179))
-[GOOD] (define-fun s181 () (Seq Int) (ite s35 s169 s180))
-[GOOD] (define-fun s182 () (Seq Int) (ite s31 s164 s181))
-[GOOD] (define-fun s183 () (Seq Int) (ite s27 s159 s182))
-[GOOD] (define-fun s184 () (Seq Int) (ite s23 s154 s183))
-[GOOD] (define-fun s185 () (Seq Int) (ite s19 s149 s184))
-[GOOD] (define-fun s186 () (Seq Int) (ite s15 s144 s185))
-[GOOD] (define-fun s187 () (Seq Int) (ite s11 s139 s186))
-[GOOD] (define-fun s188 () (Seq Int) (ite s7 s132 s187))
-[GOOD] (define-fun s189 () (Seq Int) (ite s2 s1 s188))
-[GOOD] (define-fun s190 () Bool (distinct s130 s189))
-[GOOD] (assert s48)
-[GOOD] (assert s56)
-[GOOD] (assert s65)
-[GOOD] (assert s74)
-[GOOD] (assert s83)
-[GOOD] (assert s92)
-[GOOD] (assert s101)
+[GOOD] (define-fun s170 () (Seq Int) (ite s41 s164 s169))
+[GOOD] (define-fun s171 () (Seq Int) (ite s37 s159 s170))
+[GOOD] (define-fun s172 () (Seq Int) (ite s33 s154 s171))
+[GOOD] (define-fun s173 () (Seq Int) (ite s29 s149 s172))
+[GOOD] (define-fun s174 () (Seq Int) (ite s25 s144 s173))
+[GOOD] (define-fun s175 () (Seq Int) (ite s21 s139 s174))
+[GOOD] (define-fun s176 () (Seq Int) (ite s17 s134 s175))
+[GOOD] (define-fun s177 () (Seq Int) (ite s13 s129 s176))
+[GOOD] (define-fun s178 () (Seq Int) (ite s9 s122 s177))
+[GOOD] (define-fun s179 () (Seq Int) (ite s3 s4 s178))
+[GOOD] (define-fun s180 () Bool (distinct s120 s179))
+[GOOD] (assert s47)
+[GOOD] (assert s54)
+[GOOD] (assert s62)
+[GOOD] (assert s70)
+[GOOD] (assert s78)
+[GOOD] (assert s86)
+[GOOD] (assert s94)
+[GOOD] (assert s102)
 [GOOD] (assert s110)
-[GOOD] (assert s119)
+[GOOD] (assert s118)
+[GOOD] (assert s124)
 [GOOD] (assert s128)
-[GOOD] (assert s134)
+[GOOD] (assert s133)
 [GOOD] (assert s138)
 [GOOD] (assert s143)
 [GOOD] (assert s148)
@@ -227,9 +220,7 @@
 [GOOD] (assert s158)
 [GOOD] (assert s163)
 [GOOD] (assert s168)
-[GOOD] (assert s173)
-[GOOD] (assert s178)
-[GOOD] (assert s190)
+[GOOD] (assert s180)
 [SEND] (check-sat)
 [RECV] unsat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/safe1.gold b/SBVTestSuite/GoldFiles/safe1.gold
--- a/SBVTestSuite/GoldFiles/safe1.gold
+++ b/SBVTestSuite/GoldFiles/safe1.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () Int 12)
 [GOOD] (define-fun s3 () Int 2)
diff --git a/SBVTestSuite/GoldFiles/safe2.gold b/SBVTestSuite/GoldFiles/safe2.gold
--- a/SBVTestSuite/GoldFiles/safe2.gold
+++ b/SBVTestSuite/GoldFiles/safe2.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () Int 12)
 [GOOD] (define-fun s2 () Int 2)
diff --git a/SBVTestSuite/GoldFiles/seqConcat.gold b/SBVTestSuite/GoldFiles/seqConcat.gold
--- a/SBVTestSuite/GoldFiles/seqConcat.gold
+++ b/SBVTestSuite/GoldFiles/seqConcat.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/seqConcatBad.gold b/SBVTestSuite/GoldFiles/seqConcatBad.gold
--- a/SBVTestSuite/GoldFiles/seqConcatBad.gold
+++ b/SBVTestSuite/GoldFiles/seqConcatBad.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples1.gold b/SBVTestSuite/GoldFiles/seqExamples1.gold
--- a/SBVTestSuite/GoldFiles/seqExamples1.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples1.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/seqExamples2.gold b/SBVTestSuite/GoldFiles/seqExamples2.gold
--- a/SBVTestSuite/GoldFiles/seqExamples2.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples2.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () (Seq Int) (seq.unit 2))
 [GOOD] (define-fun s3 () (Seq Int) (seq.unit 1))
diff --git a/SBVTestSuite/GoldFiles/seqExamples3.gold b/SBVTestSuite/GoldFiles/seqExamples3.gold
--- a/SBVTestSuite/GoldFiles/seqExamples3.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples3.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s4 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3) (seq.unit 4)))
 [GOOD] (define-fun s7 () (Seq Int) (seq.++ (seq.unit 3) (seq.unit 4) (seq.unit 5) (seq.unit 6)))
diff --git a/SBVTestSuite/GoldFiles/seqExamples4.gold b/SBVTestSuite/GoldFiles/seqExamples4.gold
--- a/SBVTestSuite/GoldFiles/seqExamples4.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples4.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s8 () Int 2)
 [GOOD] (define-fun s2 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2) (seq.unit 3)))
diff --git a/SBVTestSuite/GoldFiles/seqExamples5.gold b/SBVTestSuite/GoldFiles/seqExamples5.gold
--- a/SBVTestSuite/GoldFiles/seqExamples5.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples5.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () (Seq Int) (seq.++ (seq.unit 1) (seq.unit 2)))
 [GOOD] (define-fun s6 () (Seq Int) (seq.++ (seq.unit 2) (seq.unit 1)))
diff --git a/SBVTestSuite/GoldFiles/seqExamples6.gold b/SBVTestSuite/GoldFiles/seqExamples6.gold
--- a/SBVTestSuite/GoldFiles/seqExamples6.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples6.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/seqExamples7.gold b/SBVTestSuite/GoldFiles/seqExamples7.gold
--- a/SBVTestSuite/GoldFiles/seqExamples7.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples7.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/seqExamples8.gold b/SBVTestSuite/GoldFiles/seqExamples8.gold
--- a/SBVTestSuite/GoldFiles/seqExamples8.gold
+++ b/SBVTestSuite/GoldFiles/seqExamples8.gold
@@ -10,6 +10,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq Int)) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/seqIndexOf.gold b/SBVTestSuite/GoldFiles/seqIndexOf.gold
--- a/SBVTestSuite/GoldFiles/seqIndexOf.gold
+++ b/SBVTestSuite/GoldFiles/seqIndexOf.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/seqIndexOfBad.gold b/SBVTestSuite/GoldFiles/seqIndexOfBad.gold
--- a/SBVTestSuite/GoldFiles/seqIndexOfBad.gold
+++ b/SBVTestSuite/GoldFiles/seqIndexOfBad.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/set_compl1.gold b/SBVTestSuite/GoldFiles/set_compl1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_compl1.gold
@@ -0,0 +1,71 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ BitVec 8) Bool) (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false) #x6f true) #x6c true) #x68 true) #x65 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                   #x65
+                                   true)
+                            #x68
+                            true)
+                     #x6c
+                     true)
+              #x6f
+              true)))
+[GOOD] (define-fun s3 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[SEND] (get-value (s3))
+[RECV] ((s3 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) true)
+                                   #x65
+                                   false)
+                            #x68
+                            false)
+                     #x6c
+                     false)
+              #x6f
+              false)))
+[GOOD] (define-fun s4 () (Array (_ BitVec 8) Bool) ((_ map not) s3))
+[SEND] (get-value (s4))
+[RECV] ((s4 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                   #x65
+                                   true)
+                            #x68
+                            true)
+                     #x6c
+                     true)
+              #x6f
+              true)))
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) Bool) ((_ map and) s3 s0))
+[SEND] (get-value (s5))
+[RECV] ((s5 ((as const (Array (_ BitVec 8) Bool)) false)))
+[GOOD] (define-fun s6 () (Array (_ BitVec 8) Bool) ((_ map or) s3 s0))
+[SEND] (get-value (s6))
+[RECV] ((s6 ((as const (Array (_ BitVec 8) Bool)) true)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'e','h','l','o'},U - {'e','h','l','o'},{'e','h','l','o'},{},U)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_delete1.gold b/SBVTestSuite/GoldFiles/set_delete1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_delete1.gold
@@ -0,0 +1,76 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x65)
+[GOOD] (define-fun s4 () (Array (_ BitVec 8) Bool) (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false) #x6f true) #x6c true) #x68 true) #x65 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x65))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                   #x65
+                                   true)
+                            #x68
+                            true)
+                     #x6c
+                     true)
+              #x6f
+              true)))
+[GOOD] (define-fun s6 () (Array (_ BitVec 8) Bool) (store s1 s0 false))
+[SEND] (get-value (s6))
+[RECV] ((s6 (store (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                          #x65
+                                          true)
+                                   #x68
+                                   true)
+                            #x6c
+                            true)
+                     #x6f
+                     true)
+              #x65
+              false)))
+[GOOD] (define-fun s7 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) Bool) (store s7 s0 false))
+[SEND] (get-value (s8))
+[RECV] ((s8 (store (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) true)
+                                          #x65
+                                          false)
+                                   #x68
+                                   false)
+                            #x6c
+                            false)
+                     #x6f
+                     false)
+              #x65
+              false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+('e',{'e','h','l','o'},{'h','l','o'},U - {'e','h','l','o'})
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_diff1.gold b/SBVTestSuite/GoldFiles/set_diff1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_diff1.gold
@@ -0,0 +1,54 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array (_ BitVec 8) Bool) (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) Bool) (difference s0 s1))
+[SEND] (get-value (s5))
+[RECV] ((s5 ((as const (Array (_ BitVec 8) Bool)) false)))
+[GOOD] (define-fun s6 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s7 () (Array (_ BitVec 8) Bool) (difference s0 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[GOOD] (define-fun s9 () (Array (_ BitVec 8) Bool) (difference s8 s1))
+[SEND] (get-value (s9))
+[RECV] ((s9 (store ((as const (Array (_ BitVec 8) Bool)) true) #x61 false)))
+[GOOD] (define-fun s10 () (Array (_ BitVec 8) Bool) (difference s8 s6))
+[SEND] (get-value (s10))
+[RECV] ((s10 ((as const (Array (_ BitVec 8) Bool)) false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'a'},{'a'},{},{'a'},U - {'a'},{})
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_disj1.gold b/SBVTestSuite/GoldFiles/set_disj1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_disj1.gold
@@ -0,0 +1,59 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array (_ BitVec 8) Bool) (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s6 () (Array (_ BitVec 8) Bool) ((as const (Array (_ BitVec 8) Bool)) false))
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) Bool) ((_ map and) s0 s1))
+[GOOD] (define-fun s7 () Bool (= s5 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 false))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s9 () (Array (_ BitVec 8) Bool) ((_ map and) s0 s8))
+[GOOD] (define-fun s10 () Bool (= s9 s6))
+[SEND] (get-value (s10))
+[RECV] ((s10 true))
+[GOOD] (define-fun s11 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[GOOD] (define-fun s12 () (Array (_ BitVec 8) Bool) ((_ map and) s11 s1))
+[GOOD] (define-fun s13 () Bool (= s12 s6))
+[SEND] (get-value (s13))
+[RECV] ((s13 true))
+[GOOD] (define-fun s14 () (Array (_ BitVec 8) Bool) ((_ map and) s11 s8))
+[GOOD] (define-fun s15 () Bool (= s14 s6))
+[SEND] (get-value (s15))
+[RECV] ((s15 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'a'},{'a'},False,True,True,False)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_empty1.gold b/SBVTestSuite/GoldFiles/set_empty1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_empty1.gold
@@ -0,0 +1,51 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ BitVec 8) Bool) (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false) #x6f true) #x6c true) #x68 true) #x65 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                   #x65
+                                   true)
+                            #x68
+                            true)
+                     #x6c
+                     true)
+              #x6f
+              true)))
+[GOOD] (define-fun s3 () (Array (_ BitVec 8) Bool) ((as const (Array (_ BitVec 8) Bool)) false))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[SEND] (get-value (s4))
+[RECV] ((s4 false))
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[GOOD] (define-fun s6 () Bool (= s5 s3))
+[SEND] (get-value (s6))
+[RECV] ((s6 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'e','h','l','o'},False,False)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_full1.gold b/SBVTestSuite/GoldFiles/set_full1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_full1.gold
@@ -0,0 +1,51 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () (Array (_ BitVec 8) Bool) (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false) #x6f true) #x6c true) #x68 true) #x65 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                   #x65
+                                   true)
+                            #x68
+                            true)
+                     #x6c
+                     true)
+              #x6f
+              true)))
+[GOOD] (define-fun s3 () (Array (_ BitVec 8) Bool) ((as const (Array (_ BitVec 8) Bool)) true))
+[GOOD] (define-fun s4 () Bool (= s0 s3))
+[SEND] (get-value (s4))
+[RECV] ((s4 false))
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[GOOD] (define-fun s6 () Bool (= s5 s3))
+[SEND] (get-value (s6))
+[RECV] ((s6 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'e','h','l','o'},False,False)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_insert1.gold b/SBVTestSuite/GoldFiles/set_insert1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_insert1.gold
@@ -0,0 +1,76 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x65)
+[GOOD] (define-fun s4 () (Array (_ BitVec 8) Bool) (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false) #x6f true) #x6c true) #x68 true) #x65 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x65))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                   #x65
+                                   true)
+                            #x68
+                            true)
+                     #x6c
+                     true)
+              #x6f
+              true)))
+[GOOD] (define-fun s6 () (Array (_ BitVec 8) Bool) (store s1 s0 true))
+[SEND] (get-value (s6))
+[RECV] ((s6 (store (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                          #x65
+                                          true)
+                                   #x68
+                                   true)
+                            #x6c
+                            true)
+                     #x6f
+                     true)
+              #x65
+              true)))
+[GOOD] (define-fun s7 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) Bool) (store s7 s0 true))
+[SEND] (get-value (s8))
+[RECV] ((s8 (store (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) true)
+                                          #x65
+                                          false)
+                                   #x68
+                                   false)
+                            #x6c
+                            false)
+                     #x6f
+                     false)
+              #x65
+              true)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+('e',{'e','h','l','o'},{'e','h','l','o'},U - {'h','l','o'})
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_intersect1.gold b/SBVTestSuite/GoldFiles/set_intersect1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_intersect1.gold
@@ -0,0 +1,54 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array (_ BitVec 8) Bool) (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) Bool) ((_ map and) s0 s1))
+[SEND] (get-value (s5))
+[RECV] ((s5 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s6 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s7 () (Array (_ BitVec 8) Bool) ((_ map and) s0 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 ((as const (Array (_ BitVec 8) Bool)) false)))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[GOOD] (define-fun s9 () (Array (_ BitVec 8) Bool) ((_ map and) s8 s1))
+[SEND] (get-value (s9))
+[RECV] ((s9 ((as const (Array (_ BitVec 8) Bool)) false)))
+[GOOD] (define-fun s10 () (Array (_ BitVec 8) Bool) ((_ map and) s8 s6))
+[SEND] (get-value (s10))
+[RECV] ((s10 (store ((as const (Array (_ BitVec 8) Bool)) true) #x61 false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'a'},{'a'},{'a'},{},{},U - {'a'})
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_member1.gold b/SBVTestSuite/GoldFiles/set_member1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_member1.gold
@@ -0,0 +1,56 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x65)
+[GOOD] (define-fun s4 () (Array (_ BitVec 8) Bool) (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false) #x6f true) #x6c true) #x68 true) #x65 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x65))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                   #x65
+                                   true)
+                            #x68
+                            true)
+                     #x6c
+                     true)
+              #x6f
+              true)))
+[GOOD] (define-fun s6 () Bool (select s1 s0))
+[SEND] (get-value (s6))
+[RECV] ((s6 true))
+[GOOD] (define-fun s7 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s8 () Bool (select s7 s0))
+[SEND] (get-value (s8))
+[RECV] ((s8 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+('e',{'e','h','l','o'},True,False)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_notMember1.gold b/SBVTestSuite/GoldFiles/set_notMember1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_notMember1.gold
@@ -0,0 +1,58 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (_ BitVec 8) #x65)
+[GOOD] (define-fun s4 () (Array (_ BitVec 8) Bool) (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false) #x6f true) #x6c true) #x68 true) #x65 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s5 () Bool (= s1 s4))
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #x65))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store (store (store (store ((as const (Array (_ BitVec 8) Bool)) false)
+                                   #x65
+                                   true)
+                            #x68
+                            true)
+                     #x6c
+                     true)
+              #x6f
+              true)))
+[GOOD] (define-fun s6 () Bool (select s1 s0))
+[GOOD] (define-fun s7 () Bool (not s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 false))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s9 () Bool (select s8 s0))
+[GOOD] (define-fun s10 () Bool (not s9))
+[SEND] (get-value (s10))
+[RECV] ((s10 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+('e',{'e','h','l','o'},False,True)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_psubset1.gold b/SBVTestSuite/GoldFiles/set_psubset1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_psubset1.gold
@@ -0,0 +1,66 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array (_ BitVec 8) Bool) (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s5 () Bool (subset s0 s1))
+[GOOD] (define-fun s6 () Bool (= s0 s1))
+[GOOD] (define-fun s7 () Bool (not s6))
+[GOOD] (define-fun s8 () Bool (and s5 s7))
+[SEND] (get-value (s8))
+[RECV] ((s8 false))
+[GOOD] (define-fun s9 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s10 () Bool (subset s0 s9))
+[GOOD] (define-fun s11 () Bool (= s0 s9))
+[GOOD] (define-fun s12 () Bool (not s11))
+[GOOD] (define-fun s13 () Bool (and s10 s12))
+[SEND] (get-value (s13))
+[RECV] ((s13 false))
+[GOOD] (define-fun s14 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[GOOD] (define-fun s15 () Bool (subset s14 s1))
+[GOOD] (define-fun s16 () Bool (= s14 s1))
+[GOOD] (define-fun s17 () Bool (not s16))
+[GOOD] (define-fun s18 () Bool (and s15 s17))
+[SEND] (get-value (s18))
+[RECV] ((s18 false))
+[GOOD] (define-fun s19 () Bool (subset s14 s9))
+[GOOD] (define-fun s20 () Bool (= s14 s9))
+[GOOD] (define-fun s21 () Bool (not s20))
+[GOOD] (define-fun s22 () Bool (and s19 s21))
+[SEND] (get-value (s22))
+[RECV] ((s22 false))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'a'},{'a'},False,False,False,False)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_subset1.gold b/SBVTestSuite/GoldFiles/set_subset1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_subset1.gold
@@ -0,0 +1,54 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array (_ BitVec 8) Bool) (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s5 () Bool (subset s0 s1))
+[SEND] (get-value (s5))
+[RECV] ((s5 true))
+[GOOD] (define-fun s6 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s7 () Bool (subset s0 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 false))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[GOOD] (define-fun s9 () Bool (subset s8 s1))
+[SEND] (get-value (s9))
+[RECV] ((s9 false))
+[GOOD] (define-fun s10 () Bool (subset s8 s6))
+[SEND] (get-value (s10))
+[RECV] ((s10 true))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'a'},{'a'},True,False,False,True)
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_uninterp1.gold b/SBVTestSuite/GoldFiles/set_uninterp1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_uninterp1.gold
@@ -0,0 +1,124 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] (declare-datatypes ((E 0)) (((A) (B) (C))))
+[GOOD] (define-fun E_constrIndex ((x E)) Int
+          (ite (= x A) 0 (ite (= x B) 1 2))
+       )
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array E Bool))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+*** Checking Satisfiability, all solutions..
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 ((as const (Array E Bool)) false)))
+[GOOD] (define-fun s1 () (Array E Bool) ((as const (Array E Bool)) false))
+[GOOD] (define-fun s2 () Bool (= s0 s1))
+[GOOD] (define-fun s3 () Bool (not s2))
+[GOOD] (assert s3)
+Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) B true)))
+[GOOD] (define-fun s4 () (Array E Bool) (store ((as const (Array E Bool)) false) B true))
+[GOOD] (define-fun s5 () Bool (= s0 s4))
+[GOOD] (define-fun s6 () Bool (not s5))
+[GOOD] (assert s6)
+Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store ((as const (Array E Bool)) false) B true) A true)))
+[GOOD] (define-fun s7 () (Array E Bool) (store (store ((as const (Array E Bool)) false) B true) A true))
+[GOOD] (define-fun s8 () Bool (= s0 s7))
+[GOOD] (define-fun s9 () Bool (not s8))
+[GOOD] (assert s9)
+Looking for solution 4
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store (store ((as const (Array E Bool)) false) B true) C true) A true)))
+[GOOD] (define-fun s10 () (Array E Bool) (store (store (store ((as const (Array E Bool)) false) C true) B true) A true))
+[GOOD] (define-fun s11 () Bool (= s0 s10))
+[GOOD] (define-fun s12 () Bool (not s11))
+[GOOD] (assert s12)
+Looking for solution 5
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store ((as const (Array E Bool)) false) B true) C true)))
+[GOOD] (define-fun s13 () (Array E Bool) (store (store ((as const (Array E Bool)) false) C true) B true))
+[GOOD] (define-fun s14 () Bool (= s0 s13))
+[GOOD] (define-fun s15 () Bool (not s14))
+[GOOD] (assert s15)
+Looking for solution 6
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) A true)))
+[GOOD] (define-fun s16 () (Array E Bool) (store ((as const (Array E Bool)) false) A true))
+[GOOD] (define-fun s17 () Bool (= s0 s16))
+[GOOD] (define-fun s18 () Bool (not s17))
+[GOOD] (assert s18)
+Looking for solution 7
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store (store ((as const (Array E Bool)) false) C true) A true)))
+[GOOD] (define-fun s19 () (Array E Bool) (store (store ((as const (Array E Bool)) false) C true) A true))
+[GOOD] (define-fun s20 () Bool (= s0 s19))
+[GOOD] (define-fun s21 () Bool (not s20))
+[GOOD] (assert s21)
+Looking for solution 8
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) C true)))
+[GOOD] (define-fun s22 () (Array E Bool) (store ((as const (Array E Bool)) false) C true))
+[GOOD] (define-fun s23 () Bool (= s0 s22))
+[GOOD] (define-fun s24 () Bool (not s23))
+[GOOD] (assert s24)
+Looking for solution 9
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+Solution #1:
+  s0 = {} :: {E}
+Solution #2:
+  s0 = {B} :: {E}
+Solution #3:
+  s0 = {A,B} :: {E}
+Solution #4:
+  s0 = {A,B,C} :: {E}
+Solution #5:
+  s0 = {B,C} :: {E}
+Solution #6:
+  s0 = {A} :: {E}
+Solution #7:
+  s0 = {A,C} :: {E}
+Solution #8:
+  s0 = {C} :: {E}
+Found 8 different solutions.
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_uninterp2.gold b/SBVTestSuite/GoldFiles/set_uninterp2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_uninterp2.gold
@@ -0,0 +1,41 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has user-defined sorts, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] (declare-datatypes ((E 0)) (((A) (B) (C))))
+[GOOD] (define-fun E_constrIndex ((x E)) Int
+          (ite (= x A) 0 (ite (= x B) 1 2))
+       )
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array E Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array E Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Bool (distinct s0 s1))
+[GOOD] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array E Bool)) false) B true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 ((as const (Array E Bool)) false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({B},{})
+DONE!
diff --git a/SBVTestSuite/GoldFiles/set_union1.gold b/SBVTestSuite/GoldFiles/set_union1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/set_union1.gold
@@ -0,0 +1,54 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has sets, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (Array (_ BitVec 8) Bool) (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (Array (_ BitVec 8) Bool)) ; tracks user variable "a"
+[GOOD] (declare-fun s1 () (Array (_ BitVec 8) Bool)) ; tracks user variable "b"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () Bool (= s0 s2))
+[GOOD] (define-fun s4 () Bool (= s1 s2))
+[GOOD] (assert s3)
+[GOOD] (assert s4)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s5 () (Array (_ BitVec 8) Bool) ((_ map or) s0 s1))
+[SEND] (get-value (s5))
+[RECV] ((s5 (store ((as const (Array (_ BitVec 8) Bool)) false) #x61 true)))
+[GOOD] (define-fun s6 () (Array (_ BitVec 8) Bool) ((_ map not) s1))
+[GOOD] (define-fun s7 () (Array (_ BitVec 8) Bool) ((_ map or) s0 s6))
+[SEND] (get-value (s7))
+[RECV] ((s7 ((as const (Array (_ BitVec 8) Bool)) true)))
+[GOOD] (define-fun s8 () (Array (_ BitVec 8) Bool) ((_ map not) s0))
+[GOOD] (define-fun s9 () (Array (_ BitVec 8) Bool) ((_ map or) s8 s1))
+[SEND] (get-value (s9))
+[RECV] ((s9 ((as const (Array (_ BitVec 8) Bool)) true)))
+[GOOD] (define-fun s10 () (Array (_ BitVec 8) Bool) ((_ map or) s8 s6))
+[SEND] (get-value (s10))
+[RECV] ((s10 (store ((as const (Array (_ BitVec 8) Bool)) true) #x61 false)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL:
+({'a'},{'a'},{'a'},U,U,U - {'a'})
+DONE!
diff --git a/SBVTestSuite/GoldFiles/sort.gold b/SBVTestSuite/GoldFiles/sort.gold
--- a/SBVTestSuite/GoldFiles/sort.gold
+++ b/SBVTestSuite/GoldFiles/sort.gold
@@ -10,23 +10,24 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s14 () Int 1)
-[GOOD] (define-fun s26 () Int 0)
-[GOOD] (define-fun s12 () (Seq Int) (as seq.empty (Seq Int)))
+[GOOD] (define-fun s13 () Int 0)
+[GOOD] (define-fun s16 () Int 1)
+[GOOD] (define-fun s15 () (Seq Int) (as seq.empty (Seq Int)))
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () Int) ; tracks user variable "a"
 [GOOD] (declare-fun s1 () Int) ; tracks user variable "b"
 [GOOD] (declare-fun s2 () Int) ; tracks user variable "c"
-[GOOD] (declare-fun s23 () Int) ; tracks user variable "__internal_sbv_s23"
+[GOOD] (declare-fun s25 () Int) ; tracks user variable "__internal_sbv_s25"
 [GOOD] (declare-fun s34 () Int) ; tracks user variable "__internal_sbv_s34"
-[GOOD] (declare-fun s41 () Int) ; tracks user variable "__internal_sbv_s41"
-[GOOD] (declare-fun s55 () Int) ; tracks user variable "__internal_sbv_s55"
-[GOOD] (declare-fun s69 () Int) ; tracks user variable "__internal_sbv_s69"
-[GOOD] (declare-fun s93 () Int) ; tracks user variable "__internal_sbv_s93"
-[GOOD] (declare-fun s100 () Int) ; tracks user variable "__internal_sbv_s100"
-[GOOD] (declare-fun s114 () Int) ; tracks user variable "__internal_sbv_s114"
-[GOOD] (declare-fun s128 () Int) ; tracks user variable "__internal_sbv_s128"
+[GOOD] (declare-fun s40 () Int) ; tracks user variable "__internal_sbv_s40"
+[GOOD] (declare-fun s53 () Int) ; tracks user variable "__internal_sbv_s53"
+[GOOD] (declare-fun s66 () Int) ; tracks user variable "__internal_sbv_s66"
+[GOOD] (declare-fun s89 () Int) ; tracks user variable "__internal_sbv_s89"
+[GOOD] (declare-fun s95 () Int) ; tracks user variable "__internal_sbv_s95"
+[GOOD] (declare-fun s108 () Int) ; tracks user variable "__internal_sbv_s108"
+[GOOD] (declare-fun s121 () Int) ; tracks user variable "__internal_sbv_s121"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -42,184 +43,175 @@
 [GOOD] (define-fun s9 () (Seq Int) (seq.unit s2))
 [GOOD] (define-fun s10 () (Seq Int) (seq.++ s8 s9))
 [GOOD] (define-fun s11 () (Seq Int) (seq.++ s7 s10))
-[GOOD] (define-fun s13 () Bool (= s11 s12))
-[GOOD] (define-fun s15 () Int (seq.len s11))
-[GOOD] (define-fun s16 () Int (- s15 s14))
-[GOOD] (define-fun s17 () (Seq Int) (seq.extract s11 s14 s16))
-[GOOD] (define-fun s18 () Bool (= s12 s17))
-[GOOD] (define-fun s19 () Int (seq.len s17))
-[GOOD] (define-fun s20 () Int (- s19 s14))
-[GOOD] (define-fun s21 () (Seq Int) (seq.extract s17 s14 s20))
-[GOOD] (define-fun s22 () Bool (= s12 s21))
-[GOOD] (define-fun s24 () (Seq Int) (seq.unit s23))
-[GOOD] (define-fun s25 () Int (seq.len s21))
-[GOOD] (define-fun s27 () Bool (> s25 s26))
-[GOOD] (define-fun s28 () Bool (not s27))
-[GOOD] (define-fun s29 () (Seq Int) (seq.extract s21 s26 s14))
-[GOOD] (define-fun s30 () Bool (= s24 s29))
-[GOOD] (define-fun s31 () Bool (or s28 s30))
-[GOOD] (define-fun s32 () (Seq Int) (ite s22 s12 s24))
-[GOOD] (define-fun s33 () Bool (= s12 s32))
+[GOOD] (define-fun s12 () Int (seq.len s11))
+[GOOD] (define-fun s14 () Bool (= s12 s13))
+[GOOD] (define-fun s17 () Int (- s12 s16))
+[GOOD] (define-fun s18 () (Seq Int) (seq.extract s11 s16 s17))
+[GOOD] (define-fun s19 () Int (seq.len s18))
+[GOOD] (define-fun s20 () Bool (= s13 s19))
+[GOOD] (define-fun s21 () Int (- s19 s16))
+[GOOD] (define-fun s22 () (Seq Int) (seq.extract s18 s16 s21))
+[GOOD] (define-fun s23 () Int (seq.len s22))
+[GOOD] (define-fun s24 () Bool (= s13 s23))
+[GOOD] (define-fun s26 () (Seq Int) (seq.unit s25))
+[GOOD] (define-fun s27 () (Seq Int) (seq.extract s22 s13 s16))
+[GOOD] (define-fun s28 () Bool (= s26 s27))
+[GOOD] (define-fun s29 () Bool (<= s23 s13))
+[GOOD] (define-fun s30 () Bool (or s28 s29))
+[GOOD] (define-fun s31 () (Seq Int) (ite s24 s15 s26))
+[GOOD] (define-fun s32 () Int (seq.len s31))
+[GOOD] (define-fun s33 () Bool (= s13 s32))
 [GOOD] (define-fun s35 () (Seq Int) (seq.unit s34))
-[GOOD] (define-fun s36 () Bool (> s19 s26))
-[GOOD] (define-fun s37 () Bool (not s36))
-[GOOD] (define-fun s38 () (Seq Int) (seq.extract s17 s26 s14))
-[GOOD] (define-fun s39 () Bool (= s35 s38))
-[GOOD] (define-fun s40 () Bool (or s37 s39))
-[GOOD] (define-fun s42 () (Seq Int) (seq.unit s41))
-[GOOD] (define-fun s43 () Int (seq.len s32))
-[GOOD] (define-fun s44 () Bool (> s43 s26))
-[GOOD] (define-fun s45 () Bool (not s44))
-[GOOD] (define-fun s46 () (Seq Int) (seq.extract s32 s26 s14))
-[GOOD] (define-fun s47 () Bool (= s42 s46))
-[GOOD] (define-fun s48 () Bool (or s45 s47))
-[GOOD] (define-fun s49 () Bool (< s34 s41))
-[GOOD] (define-fun s50 () Int (- s43 s14))
-[GOOD] (define-fun s51 () (Seq Int) (seq.extract s32 s14 s50))
-[GOOD] (define-fun s52 () (Seq Int) (seq.++ s42 s51))
-[GOOD] (define-fun s53 () (Seq Int) (seq.++ s35 s52))
-[GOOD] (define-fun s54 () Bool (= s12 s51))
-[GOOD] (define-fun s56 () (Seq Int) (seq.unit s55))
-[GOOD] (define-fun s57 () Int (seq.len s51))
-[GOOD] (define-fun s58 () Bool (> s57 s26))
-[GOOD] (define-fun s59 () Bool (not s58))
-[GOOD] (define-fun s60 () (Seq Int) (seq.extract s51 s26 s14))
-[GOOD] (define-fun s61 () Bool (= s56 s60))
-[GOOD] (define-fun s62 () Bool (or s59 s61))
-[GOOD] (define-fun s63 () Bool (< s34 s55))
-[GOOD] (define-fun s64 () Int (- s57 s14))
-[GOOD] (define-fun s65 () (Seq Int) (seq.extract s51 s14 s64))
-[GOOD] (define-fun s66 () (Seq Int) (seq.++ s56 s65))
-[GOOD] (define-fun s67 () (Seq Int) (seq.++ s35 s66))
-[GOOD] (define-fun s68 () Bool (= s12 s65))
-[GOOD] (define-fun s70 () (Seq Int) (seq.unit s69))
-[GOOD] (define-fun s71 () Int (seq.len s65))
-[GOOD] (define-fun s72 () Bool (> s71 s26))
-[GOOD] (define-fun s73 () Bool (not s72))
-[GOOD] (define-fun s74 () (Seq Int) (seq.extract s65 s26 s14))
-[GOOD] (define-fun s75 () Bool (= s70 s74))
-[GOOD] (define-fun s76 () Bool (or s73 s75))
-[GOOD] (define-fun s77 () Bool (< s34 s69))
-[GOOD] (define-fun s78 () Int (- s71 s14))
-[GOOD] (define-fun s79 () (Seq Int) (seq.extract s65 s14 s78))
-[GOOD] (define-fun s80 () (Seq Int) (seq.++ s70 s79))
-[GOOD] (define-fun s81 () (Seq Int) (seq.++ s35 s80))
-[GOOD] (define-fun s82 () (Seq Int) (seq.++ s70 s35))
-[GOOD] (define-fun s83 () (Seq Int) (ite s77 s81 s82))
-[GOOD] (define-fun s84 () (Seq Int) (ite s68 s35 s83))
-[GOOD] (define-fun s85 () (Seq Int) (seq.++ s56 s84))
-[GOOD] (define-fun s86 () (Seq Int) (ite s63 s67 s85))
-[GOOD] (define-fun s87 () (Seq Int) (ite s54 s35 s86))
-[GOOD] (define-fun s88 () (Seq Int) (seq.++ s42 s87))
-[GOOD] (define-fun s89 () (Seq Int) (ite s49 s53 s88))
-[GOOD] (define-fun s90 () (Seq Int) (ite s33 s35 s89))
-[GOOD] (define-fun s91 () (Seq Int) (ite s18 s12 s90))
-[GOOD] (define-fun s92 () Bool (= s12 s91))
-[GOOD] (define-fun s94 () (Seq Int) (seq.unit s93))
-[GOOD] (define-fun s95 () Bool (> s15 s26))
-[GOOD] (define-fun s96 () Bool (not s95))
-[GOOD] (define-fun s97 () (Seq Int) (seq.extract s11 s26 s14))
-[GOOD] (define-fun s98 () Bool (= s94 s97))
-[GOOD] (define-fun s99 () Bool (or s96 s98))
-[GOOD] (define-fun s101 () (Seq Int) (seq.unit s100))
-[GOOD] (define-fun s102 () Int (seq.len s91))
-[GOOD] (define-fun s103 () Bool (> s102 s26))
-[GOOD] (define-fun s104 () Bool (not s103))
-[GOOD] (define-fun s105 () (Seq Int) (seq.extract s91 s26 s14))
-[GOOD] (define-fun s106 () Bool (= s101 s105))
-[GOOD] (define-fun s107 () Bool (or s104 s106))
-[GOOD] (define-fun s108 () Bool (< s93 s100))
-[GOOD] (define-fun s109 () Int (- s102 s14))
-[GOOD] (define-fun s110 () (Seq Int) (seq.extract s91 s14 s109))
-[GOOD] (define-fun s111 () (Seq Int) (seq.++ s101 s110))
-[GOOD] (define-fun s112 () (Seq Int) (seq.++ s94 s111))
-[GOOD] (define-fun s113 () Bool (= s12 s110))
-[GOOD] (define-fun s115 () (Seq Int) (seq.unit s114))
-[GOOD] (define-fun s116 () Int (seq.len s110))
-[GOOD] (define-fun s117 () Bool (> s116 s26))
-[GOOD] (define-fun s118 () Bool (not s117))
-[GOOD] (define-fun s119 () (Seq Int) (seq.extract s110 s26 s14))
-[GOOD] (define-fun s120 () Bool (= s115 s119))
-[GOOD] (define-fun s121 () Bool (or s118 s120))
-[GOOD] (define-fun s122 () Bool (< s93 s114))
-[GOOD] (define-fun s123 () Int (- s116 s14))
-[GOOD] (define-fun s124 () (Seq Int) (seq.extract s110 s14 s123))
-[GOOD] (define-fun s125 () (Seq Int) (seq.++ s115 s124))
-[GOOD] (define-fun s126 () (Seq Int) (seq.++ s94 s125))
-[GOOD] (define-fun s127 () Bool (= s12 s124))
-[GOOD] (define-fun s129 () (Seq Int) (seq.unit s128))
-[GOOD] (define-fun s130 () Int (seq.len s124))
-[GOOD] (define-fun s131 () Bool (> s130 s26))
-[GOOD] (define-fun s132 () Bool (not s131))
-[GOOD] (define-fun s133 () (Seq Int) (seq.extract s124 s26 s14))
-[GOOD] (define-fun s134 () Bool (= s129 s133))
-[GOOD] (define-fun s135 () Bool (or s132 s134))
-[GOOD] (define-fun s136 () Bool (< s93 s128))
-[GOOD] (define-fun s137 () Int (- s130 s14))
-[GOOD] (define-fun s138 () (Seq Int) (seq.extract s124 s14 s137))
-[GOOD] (define-fun s139 () (Seq Int) (seq.++ s129 s138))
-[GOOD] (define-fun s140 () (Seq Int) (seq.++ s94 s139))
-[GOOD] (define-fun s141 () (Seq Int) (seq.++ s129 s94))
-[GOOD] (define-fun s142 () (Seq Int) (ite s136 s140 s141))
-[GOOD] (define-fun s143 () (Seq Int) (ite s127 s94 s142))
-[GOOD] (define-fun s144 () (Seq Int) (seq.++ s115 s143))
-[GOOD] (define-fun s145 () (Seq Int) (ite s122 s126 s144))
-[GOOD] (define-fun s146 () (Seq Int) (ite s113 s94 s145))
-[GOOD] (define-fun s147 () (Seq Int) (seq.++ s101 s146))
-[GOOD] (define-fun s148 () (Seq Int) (ite s108 s112 s147))
-[GOOD] (define-fun s149 () (Seq Int) (ite s92 s94 s148))
-[GOOD] (define-fun s150 () (Seq Int) (ite s13 s12 s149))
-[GOOD] (define-fun s151 () Bool (= s11 s150))
-[GOOD] (define-fun s152 () Bool (or s6 s151))
-[GOOD] (define-fun s153 () Bool (<= s0 s2))
-[GOOD] (define-fun s154 () Bool (<= s2 s1))
-[GOOD] (define-fun s155 () Bool (and s153 s154))
-[GOOD] (define-fun s156 () Bool (not s155))
-[GOOD] (define-fun s157 () (Seq Int) (seq.++ s9 s8))
-[GOOD] (define-fun s158 () (Seq Int) (seq.++ s7 s157))
-[GOOD] (define-fun s159 () Bool (= s150 s158))
-[GOOD] (define-fun s160 () Bool (or s156 s159))
-[GOOD] (define-fun s161 () Bool (<= s1 s0))
-[GOOD] (define-fun s162 () Bool (and s153 s161))
-[GOOD] (define-fun s163 () Bool (not s162))
-[GOOD] (define-fun s164 () (Seq Int) (seq.++ s7 s9))
-[GOOD] (define-fun s165 () (Seq Int) (seq.++ s8 s164))
-[GOOD] (define-fun s166 () Bool (= s150 s165))
-[GOOD] (define-fun s167 () Bool (or s163 s166))
-[GOOD] (define-fun s168 () Bool (<= s2 s0))
-[GOOD] (define-fun s169 () Bool (and s4 s168))
-[GOOD] (define-fun s170 () Bool (not s169))
-[GOOD] (define-fun s171 () (Seq Int) (seq.++ s9 s7))
-[GOOD] (define-fun s172 () (Seq Int) (seq.++ s8 s171))
-[GOOD] (define-fun s173 () Bool (= s150 s172))
-[GOOD] (define-fun s174 () Bool (or s170 s173))
-[GOOD] (define-fun s175 () Bool (and s3 s168))
-[GOOD] (define-fun s176 () Bool (not s175))
-[GOOD] (define-fun s177 () (Seq Int) (seq.++ s7 s8))
-[GOOD] (define-fun s178 () (Seq Int) (seq.++ s9 s177))
-[GOOD] (define-fun s179 () Bool (= s150 s178))
-[GOOD] (define-fun s180 () Bool (or s176 s179))
-[GOOD] (define-fun s181 () Bool (and s154 s161))
-[GOOD] (define-fun s182 () Bool (not s181))
-[GOOD] (define-fun s183 () (Seq Int) (seq.++ s8 s7))
-[GOOD] (define-fun s184 () (Seq Int) (seq.++ s9 s183))
-[GOOD] (define-fun s185 () Bool (= s150 s184))
-[GOOD] (define-fun s186 () Bool (or s182 s185))
-[GOOD] (assert s31)
-[GOOD] (assert s40)
-[GOOD] (assert s48)
-[GOOD] (assert s62)
-[GOOD] (assert s76)
-[GOOD] (assert s99)
-[GOOD] (assert s107)
-[GOOD] (assert s121)
-[GOOD] (assert s135)
-[GOOD] (assert s152)
-[GOOD] (assert s160)
-[GOOD] (assert s167)
-[GOOD] (assert s174)
-[GOOD] (assert s180)
-[GOOD] (assert s186)
+[GOOD] (define-fun s36 () (Seq Int) (seq.extract s18 s13 s16))
+[GOOD] (define-fun s37 () Bool (= s35 s36))
+[GOOD] (define-fun s38 () Bool (<= s19 s13))
+[GOOD] (define-fun s39 () Bool (or s37 s38))
+[GOOD] (define-fun s41 () (Seq Int) (seq.unit s40))
+[GOOD] (define-fun s42 () (Seq Int) (seq.extract s31 s13 s16))
+[GOOD] (define-fun s43 () Bool (= s41 s42))
+[GOOD] (define-fun s44 () Bool (<= s32 s13))
+[GOOD] (define-fun s45 () Bool (or s43 s44))
+[GOOD] (define-fun s46 () Bool (< s34 s40))
+[GOOD] (define-fun s47 () Int (- s32 s16))
+[GOOD] (define-fun s48 () (Seq Int) (seq.extract s31 s16 s47))
+[GOOD] (define-fun s49 () (Seq Int) (seq.++ s41 s48))
+[GOOD] (define-fun s50 () (Seq Int) (seq.++ s35 s49))
+[GOOD] (define-fun s51 () Int (seq.len s48))
+[GOOD] (define-fun s52 () Bool (= s13 s51))
+[GOOD] (define-fun s54 () (Seq Int) (seq.unit s53))
+[GOOD] (define-fun s55 () (Seq Int) (seq.extract s48 s13 s16))
+[GOOD] (define-fun s56 () Bool (= s54 s55))
+[GOOD] (define-fun s57 () Bool (<= s51 s13))
+[GOOD] (define-fun s58 () Bool (or s56 s57))
+[GOOD] (define-fun s59 () Bool (< s34 s53))
+[GOOD] (define-fun s60 () Int (- s51 s16))
+[GOOD] (define-fun s61 () (Seq Int) (seq.extract s48 s16 s60))
+[GOOD] (define-fun s62 () (Seq Int) (seq.++ s54 s61))
+[GOOD] (define-fun s63 () (Seq Int) (seq.++ s35 s62))
+[GOOD] (define-fun s64 () Int (seq.len s61))
+[GOOD] (define-fun s65 () Bool (= s13 s64))
+[GOOD] (define-fun s67 () (Seq Int) (seq.unit s66))
+[GOOD] (define-fun s68 () (Seq Int) (seq.extract s61 s13 s16))
+[GOOD] (define-fun s69 () Bool (= s67 s68))
+[GOOD] (define-fun s70 () Bool (<= s64 s13))
+[GOOD] (define-fun s71 () Bool (or s69 s70))
+[GOOD] (define-fun s72 () Bool (< s34 s66))
+[GOOD] (define-fun s73 () Int (- s64 s16))
+[GOOD] (define-fun s74 () (Seq Int) (seq.extract s61 s16 s73))
+[GOOD] (define-fun s75 () (Seq Int) (seq.++ s67 s74))
+[GOOD] (define-fun s76 () (Seq Int) (seq.++ s35 s75))
+[GOOD] (define-fun s77 () (Seq Int) (seq.++ s67 s35))
+[GOOD] (define-fun s78 () (Seq Int) (ite s72 s76 s77))
+[GOOD] (define-fun s79 () (Seq Int) (ite s65 s35 s78))
+[GOOD] (define-fun s80 () (Seq Int) (seq.++ s54 s79))
+[GOOD] (define-fun s81 () (Seq Int) (ite s59 s63 s80))
+[GOOD] (define-fun s82 () (Seq Int) (ite s52 s35 s81))
+[GOOD] (define-fun s83 () (Seq Int) (seq.++ s41 s82))
+[GOOD] (define-fun s84 () (Seq Int) (ite s46 s50 s83))
+[GOOD] (define-fun s85 () (Seq Int) (ite s33 s35 s84))
+[GOOD] (define-fun s86 () (Seq Int) (ite s20 s15 s85))
+[GOOD] (define-fun s87 () Int (seq.len s86))
+[GOOD] (define-fun s88 () Bool (= s13 s87))
+[GOOD] (define-fun s90 () (Seq Int) (seq.unit s89))
+[GOOD] (define-fun s91 () (Seq Int) (seq.extract s11 s13 s16))
+[GOOD] (define-fun s92 () Bool (= s90 s91))
+[GOOD] (define-fun s93 () Bool (<= s12 s13))
+[GOOD] (define-fun s94 () Bool (or s92 s93))
+[GOOD] (define-fun s96 () (Seq Int) (seq.unit s95))
+[GOOD] (define-fun s97 () (Seq Int) (seq.extract s86 s13 s16))
+[GOOD] (define-fun s98 () Bool (= s96 s97))
+[GOOD] (define-fun s99 () Bool (<= s87 s13))
+[GOOD] (define-fun s100 () Bool (or s98 s99))
+[GOOD] (define-fun s101 () Bool (< s89 s95))
+[GOOD] (define-fun s102 () Int (- s87 s16))
+[GOOD] (define-fun s103 () (Seq Int) (seq.extract s86 s16 s102))
+[GOOD] (define-fun s104 () (Seq Int) (seq.++ s96 s103))
+[GOOD] (define-fun s105 () (Seq Int) (seq.++ s90 s104))
+[GOOD] (define-fun s106 () Int (seq.len s103))
+[GOOD] (define-fun s107 () Bool (= s13 s106))
+[GOOD] (define-fun s109 () (Seq Int) (seq.unit s108))
+[GOOD] (define-fun s110 () (Seq Int) (seq.extract s103 s13 s16))
+[GOOD] (define-fun s111 () Bool (= s109 s110))
+[GOOD] (define-fun s112 () Bool (<= s106 s13))
+[GOOD] (define-fun s113 () Bool (or s111 s112))
+[GOOD] (define-fun s114 () Bool (< s89 s108))
+[GOOD] (define-fun s115 () Int (- s106 s16))
+[GOOD] (define-fun s116 () (Seq Int) (seq.extract s103 s16 s115))
+[GOOD] (define-fun s117 () (Seq Int) (seq.++ s109 s116))
+[GOOD] (define-fun s118 () (Seq Int) (seq.++ s90 s117))
+[GOOD] (define-fun s119 () Int (seq.len s116))
+[GOOD] (define-fun s120 () Bool (= s13 s119))
+[GOOD] (define-fun s122 () (Seq Int) (seq.unit s121))
+[GOOD] (define-fun s123 () (Seq Int) (seq.extract s116 s13 s16))
+[GOOD] (define-fun s124 () Bool (= s122 s123))
+[GOOD] (define-fun s125 () Bool (<= s119 s13))
+[GOOD] (define-fun s126 () Bool (or s124 s125))
+[GOOD] (define-fun s127 () Bool (< s89 s121))
+[GOOD] (define-fun s128 () Int (- s119 s16))
+[GOOD] (define-fun s129 () (Seq Int) (seq.extract s116 s16 s128))
+[GOOD] (define-fun s130 () (Seq Int) (seq.++ s122 s129))
+[GOOD] (define-fun s131 () (Seq Int) (seq.++ s90 s130))
+[GOOD] (define-fun s132 () (Seq Int) (seq.++ s122 s90))
+[GOOD] (define-fun s133 () (Seq Int) (ite s127 s131 s132))
+[GOOD] (define-fun s134 () (Seq Int) (ite s120 s90 s133))
+[GOOD] (define-fun s135 () (Seq Int) (seq.++ s109 s134))
+[GOOD] (define-fun s136 () (Seq Int) (ite s114 s118 s135))
+[GOOD] (define-fun s137 () (Seq Int) (ite s107 s90 s136))
+[GOOD] (define-fun s138 () (Seq Int) (seq.++ s96 s137))
+[GOOD] (define-fun s139 () (Seq Int) (ite s101 s105 s138))
+[GOOD] (define-fun s140 () (Seq Int) (ite s88 s90 s139))
+[GOOD] (define-fun s141 () (Seq Int) (ite s14 s15 s140))
+[GOOD] (define-fun s142 () Bool (= s11 s141))
+[GOOD] (define-fun s143 () Bool (or s6 s142))
+[GOOD] (define-fun s144 () Bool (<= s0 s2))
+[GOOD] (define-fun s145 () Bool (<= s2 s1))
+[GOOD] (define-fun s146 () Bool (and s144 s145))
+[GOOD] (define-fun s147 () Bool (not s146))
+[GOOD] (define-fun s148 () (Seq Int) (seq.++ s9 s8))
+[GOOD] (define-fun s149 () (Seq Int) (seq.++ s7 s148))
+[GOOD] (define-fun s150 () Bool (= s141 s149))
+[GOOD] (define-fun s151 () Bool (or s147 s150))
+[GOOD] (define-fun s152 () Bool (<= s1 s0))
+[GOOD] (define-fun s153 () Bool (and s144 s152))
+[GOOD] (define-fun s154 () Bool (not s153))
+[GOOD] (define-fun s155 () (Seq Int) (seq.++ s7 s9))
+[GOOD] (define-fun s156 () (Seq Int) (seq.++ s8 s155))
+[GOOD] (define-fun s157 () Bool (= s141 s156))
+[GOOD] (define-fun s158 () Bool (or s154 s157))
+[GOOD] (define-fun s159 () Bool (<= s2 s0))
+[GOOD] (define-fun s160 () Bool (and s4 s159))
+[GOOD] (define-fun s161 () Bool (not s160))
+[GOOD] (define-fun s162 () (Seq Int) (seq.++ s9 s7))
+[GOOD] (define-fun s163 () (Seq Int) (seq.++ s8 s162))
+[GOOD] (define-fun s164 () Bool (= s141 s163))
+[GOOD] (define-fun s165 () Bool (or s161 s164))
+[GOOD] (define-fun s166 () Bool (and s3 s159))
+[GOOD] (define-fun s167 () Bool (not s166))
+[GOOD] (define-fun s168 () (Seq Int) (seq.++ s7 s8))
+[GOOD] (define-fun s169 () (Seq Int) (seq.++ s9 s168))
+[GOOD] (define-fun s170 () Bool (= s141 s169))
+[GOOD] (define-fun s171 () Bool (or s167 s170))
+[GOOD] (define-fun s172 () Bool (and s145 s152))
+[GOOD] (define-fun s173 () Bool (not s172))
+[GOOD] (define-fun s174 () (Seq Int) (seq.++ s8 s7))
+[GOOD] (define-fun s175 () (Seq Int) (seq.++ s9 s174))
+[GOOD] (define-fun s176 () Bool (= s141 s175))
+[GOOD] (define-fun s177 () Bool (or s173 s176))
+[GOOD] (assert s30)
+[GOOD] (assert s39)
+[GOOD] (assert s45)
+[GOOD] (assert s58)
+[GOOD] (assert s71)
+[GOOD] (assert s94)
+[GOOD] (assert s100)
+[GOOD] (assert s113)
+[GOOD] (assert s126)
+[GOOD] (assert s143)
+[GOOD] (assert s151)
+[GOOD] (assert s158)
+[GOOD] (assert s165)
+[GOOD] (assert s171)
+[GOOD] (assert s177)
 [SEND] (check-sat)
 [RECV] sat
 *** Solver   : Z3
diff --git a/SBVTestSuite/GoldFiles/strConcat.gold b/SBVTestSuite/GoldFiles/strConcat.gold
--- a/SBVTestSuite/GoldFiles/strConcat.gold
+++ b/SBVTestSuite/GoldFiles/strConcat.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/strConcatBad.gold b/SBVTestSuite/GoldFiles/strConcatBad.gold
--- a/SBVTestSuite/GoldFiles/strConcatBad.gold
+++ b/SBVTestSuite/GoldFiles/strConcatBad.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/strExamples1.gold b/SBVTestSuite/GoldFiles/strExamples1.gold
--- a/SBVTestSuite/GoldFiles/strExamples1.gold
+++ b/SBVTestSuite/GoldFiles/strExamples1.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/strExamples10.gold b/SBVTestSuite/GoldFiles/strExamples10.gold
--- a/SBVTestSuite/GoldFiles/strExamples10.gold
+++ b/SBVTestSuite/GoldFiles/strExamples10.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () Int 6)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/strExamples11.gold b/SBVTestSuite/GoldFiles/strExamples11.gold
--- a/SBVTestSuite/GoldFiles/strExamples11.gold
+++ b/SBVTestSuite/GoldFiles/strExamples11.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () Int 11)
 [GOOD] (define-fun s4 () String "11")
diff --git a/SBVTestSuite/GoldFiles/strExamples12.gold b/SBVTestSuite/GoldFiles/strExamples12.gold
--- a/SBVTestSuite/GoldFiles/strExamples12.gold
+++ b/SBVTestSuite/GoldFiles/strExamples12.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () Int (- 2))
 [GOOD] (define-fun s4 () String "")
diff --git a/SBVTestSuite/GoldFiles/strExamples13.gold b/SBVTestSuite/GoldFiles/strExamples13.gold
--- a/SBVTestSuite/GoldFiles/strExamples13.gold
+++ b/SBVTestSuite/GoldFiles/strExamples13.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s4 () Int 13)
 [GOOD] (define-fun s1 () String "13")
diff --git a/SBVTestSuite/GoldFiles/strExamples2.gold b/SBVTestSuite/GoldFiles/strExamples2.gold
--- a/SBVTestSuite/GoldFiles/strExamples2.gold
+++ b/SBVTestSuite/GoldFiles/strExamples2.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s1 () String "b")
 [GOOD] (define-fun s3 () String "a")
diff --git a/SBVTestSuite/GoldFiles/strExamples3.gold b/SBVTestSuite/GoldFiles/strExamples3.gold
--- a/SBVTestSuite/GoldFiles/strExamples3.gold
+++ b/SBVTestSuite/GoldFiles/strExamples3.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s4 () String "abcd")
 [GOOD] (define-fun s7 () String "cdef")
diff --git a/SBVTestSuite/GoldFiles/strExamples4.gold b/SBVTestSuite/GoldFiles/strExamples4.gold
--- a/SBVTestSuite/GoldFiles/strExamples4.gold
+++ b/SBVTestSuite/GoldFiles/strExamples4.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s8 () Int 2)
 [GOOD] (define-fun s2 () String "abc")
diff --git a/SBVTestSuite/GoldFiles/strExamples5.gold b/SBVTestSuite/GoldFiles/strExamples5.gold
--- a/SBVTestSuite/GoldFiles/strExamples5.gold
+++ b/SBVTestSuite/GoldFiles/strExamples5.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () String "ab")
 [GOOD] (define-fun s6 () String "ba")
diff --git a/SBVTestSuite/GoldFiles/strExamples6.gold b/SBVTestSuite/GoldFiles/strExamples6.gold
--- a/SBVTestSuite/GoldFiles/strExamples6.gold
+++ b/SBVTestSuite/GoldFiles/strExamples6.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () String) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/strExamples7.gold b/SBVTestSuite/GoldFiles/strExamples7.gold
--- a/SBVTestSuite/GoldFiles/strExamples7.gold
+++ b/SBVTestSuite/GoldFiles/strExamples7.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () String) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/strExamples8.gold b/SBVTestSuite/GoldFiles/strExamples8.gold
--- a/SBVTestSuite/GoldFiles/strExamples8.gold
+++ b/SBVTestSuite/GoldFiles/strExamples8.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () String) ; tracks user variable "a"
diff --git a/SBVTestSuite/GoldFiles/strExamples9.gold b/SBVTestSuite/GoldFiles/strExamples9.gold
--- a/SBVTestSuite/GoldFiles/strExamples9.gold
+++ b/SBVTestSuite/GoldFiles/strExamples9.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () Int 6)
 [GOOD] ; --- skolem constants ---
diff --git a/SBVTestSuite/GoldFiles/strIndexOf.gold b/SBVTestSuite/GoldFiles/strIndexOf.gold
--- a/SBVTestSuite/GoldFiles/strIndexOf.gold
+++ b/SBVTestSuite/GoldFiles/strIndexOf.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/strIndexOfBad.gold b/SBVTestSuite/GoldFiles/strIndexOfBad.gold
--- a/SBVTestSuite/GoldFiles/strIndexOfBad.gold
+++ b/SBVTestSuite/GoldFiles/strIndexOfBad.gold
@@ -8,6 +8,7 @@
 [GOOD] (set-logic ALL) ; external query, using all logics.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] ; --- constant tables ---
diff --git a/SBVTestSuite/GoldFiles/sumBimapPlus.gold b/SBVTestSuite/GoldFiles/sumBimapPlus.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumBimapPlus.gold
@@ -0,0 +1,50 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 1)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVEither Int Int)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int (get_left_SBVEither s0))
+[GOOD] (define-fun s3 () Int (+ s1 s2))
+[GOOD] (define-fun s4 () (SBVEither Int Int) (left_SBVEither s3))
+[GOOD] (define-fun s5 () Int (get_right_SBVEither s0))
+[GOOD] (define-fun s6 () Int (+ s2 s5))
+[GOOD] (define-fun s7 () (SBVEither Int Int) (right_SBVEither s6))
+[GOOD] (define-fun s8 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Int))) s0))
+[GOOD] (define-fun s9 () (SBVEither Int Int) (ite s8 s4 s7))
+[GOOD] (define-fun s10 () Int (get_left_SBVEither s9))
+[GOOD] (define-fun s11 () Int (get_right_SBVEither s9))
+[GOOD] (define-fun s12 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Int))) s9))
+[GOOD] (define-fun s13 () Int (ite s12 s10 s11))
+[GOOD] (define-fun s14 () Int (ite s8 s1 s5))
+[GOOD] (define-fun s15 () Int (+ s2 s14))
+[GOOD] (define-fun s16 () Bool (= s13 s15))
+[GOOD] (assert s16)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (left_SBVEither 0)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Left 0 :: Either Integer Integer)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumEitherSat.gold b/SBVTestSuite/GoldFiles/sumEitherSat.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumEitherSat.gold
@@ -0,0 +1,41 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () Int 0)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVEither Int Bool)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Int (get_left_SBVEither s0))
+[GOOD] (define-fun s3 () Bool (> s1 s2))
+[GOOD] (define-fun s4 () Bool (get_right_SBVEither s0))
+[GOOD] (define-fun s5 () Bool (not s4))
+[GOOD] (define-fun s6 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s0))
+[GOOD] (define-fun s7 () Bool (ite s6 s3 s5))
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (right_SBVEither false)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Right False :: Either Integer Bool)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumLiftEither.gold b/SBVTestSuite/GoldFiles/sumLiftEither.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumLiftEither.gold
@@ -0,0 +1,44 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
+[GOOD] (declare-fun s1 () (_ BitVec 8)) ; tracks user variable "c"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () (SBVEither Int (_ BitVec 8)) (left_SBVEither s0))
+[GOOD] (define-fun s3 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int (_ BitVec 8)))) s2))
+[GOOD] (define-fun s4 () Bool (ite s3 true false))
+[GOOD] (define-fun s5 () (SBVEither Int (_ BitVec 8)) (right_SBVEither s1))
+[GOOD] (define-fun s6 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int (_ BitVec 8)))) s5))
+[GOOD] (define-fun s7 () Bool (ite s6 false true))
+[GOOD] (assert s4)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+[SEND] (get-value (s1))
+[RECV] ((s1 #x00))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("i",0 :: Integer),("c",'\NUL' :: Char)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumLiftMaybe.gold b/SBVTestSuite/GoldFiles/sumLiftMaybe.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumLiftMaybe.gold
@@ -0,0 +1,37 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s2 () (SBVMaybe Int) (as nothing_SBVMaybe (SBVMaybe Int)))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "i"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () (SBVMaybe Int) (just_SBVMaybe s0))
+[GOOD] (define-fun s3 () Bool (distinct s1 s2))
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 0))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("i",0 :: Integer)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumMaybe.gold b/SBVTestSuite/GoldFiles/sumMaybe.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumMaybe.gold
@@ -0,0 +1,56 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s5 () Int 1)
+[GOOD] (define-fun s15 () Int 0)
+[GOOD] (define-fun s3 () (SBVMaybe Int) (as nothing_SBVMaybe (SBVMaybe Int)))
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVMaybe Int)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s1 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s0))
+[GOOD] (define-fun s2 () Bool (ite s1 true false))
+[GOOD] (define-fun s4 () Int (get_just_SBVMaybe s0))
+[GOOD] (define-fun s6 () Int (+ s4 s5))
+[GOOD] (define-fun s7 () (SBVMaybe Int) (just_SBVMaybe s6))
+[GOOD] (define-fun s8 () (SBVMaybe Int) (ite s1 s3 s7))
+[GOOD] (define-fun s9 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s8))
+[GOOD] (define-fun s10 () Bool (ite s9 true false))
+[GOOD] (define-fun s11 () Bool (= s2 s10))
+[GOOD] (define-fun s12 () Bool (ite s1 false true))
+[GOOD] (define-fun s13 () Bool (ite s9 false true))
+[GOOD] (define-fun s14 () Bool (= s12 s13))
+[GOOD] (define-fun s16 () Int (ite s1 s15 s4))
+[GOOD] (define-fun s17 () Int (get_just_SBVMaybe s8))
+[GOOD] (define-fun s18 () Int (ite s9 s15 s17))
+[GOOD] (define-fun s19 () Int (- s18 s5))
+[GOOD] (define-fun s20 () Bool (= s16 s19))
+[GOOD] (assert s11)
+[GOOD] (assert s14)
+[GOOD] (assert s20)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (just_SBVMaybe 0)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("x",Just 0 :: Maybe Integer)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumMaybeBoth.gold b/SBVTestSuite/GoldFiles/sumMaybeBoth.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumMaybeBoth.gold
@@ -0,0 +1,45 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVEither Int Int))
+[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Int))) s0))
+[GOOD] (define-fun s3 () Bool (ite s2 true false))
+[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s1))
+[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (assert s3)
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (left_SBVEither 0)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (just_SBVMaybe 1)))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Left 0 :: Either Integer Integer),("s1",Just 1 :: Maybe Integer)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumMergeEither1.gold b/SBVTestSuite/GoldFiles/sumMergeEither1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumMergeEither1.gold
@@ -0,0 +1,43 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVEither Int Bool))
+[GOOD] (declare-fun s1 () (SBVEither Int Bool))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (SBVEither Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s3))
+[GOOD] (define-fun s5 () Bool (ite s4 true false))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (left_SBVEither 0)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (right_SBVEither false)))
+[SEND] (get-value (s2))
+[RECV] ((s2 true))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Left 0 :: Either Integer Bool),("s1",Right False :: Either Integer Bool),("s2",True :: Bool)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumMergeEither2.gold b/SBVTestSuite/GoldFiles/sumMergeEither2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumMergeEither2.gold
@@ -0,0 +1,43 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVEither 2)) ((par (T1 T2)
+                                           ((left_SBVEither  (get_left_SBVEither  T1))
+                                            (right_SBVEither (get_right_SBVEither T2))))))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVEither Int Bool))
+[GOOD] (declare-fun s1 () (SBVEither Int Bool))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (SBVEither Int Bool) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((_ is (left_SBVEither (Int) (SBVEither Int Bool))) s3))
+[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (right_SBVEither false)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (right_SBVEither false)))
+[SEND] (get-value (s2))
+[RECV] ((s2 true))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Right False :: Either Integer Bool),("s1",Right False :: Either Integer Bool),("s2",True :: Bool)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumMergeMaybe1.gold b/SBVTestSuite/GoldFiles/sumMergeMaybe1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumMergeMaybe1.gold
@@ -0,0 +1,43 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVMaybe Int))
+[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (SBVMaybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s3))
+[GOOD] (define-fun s5 () Bool (ite s4 true false))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 nothing_SBVMaybe))
+[SEND] (get-value (s1))
+[RECV] ((s1 (just_SBVMaybe 0)))
+[SEND] (get-value (s2))
+[RECV] ((s2 true))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Nothing :: Maybe Integer),("s1",Just 0 :: Maybe Integer),("s2",True :: Bool)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/sumMergeMaybe2.gold b/SBVTestSuite/GoldFiles/sumMergeMaybe2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/sumMergeMaybe2.gold
@@ -0,0 +1,43 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] (declare-datatypes ((SBVMaybe 1)) ((par (T)
+                                           ((nothing_SBVMaybe)
+                                            (just_SBVMaybe (get_just_SBVMaybe T))))))
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (SBVMaybe Int))
+[GOOD] (declare-fun s1 () (SBVMaybe Int))
+[GOOD] (declare-fun s2 () Bool)
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s3 () (SBVMaybe Int) (ite s2 s0 s1))
+[GOOD] (define-fun s4 () Bool ((_ is (nothing_SBVMaybe () (SBVMaybe Int))) s3))
+[GOOD] (define-fun s5 () Bool (ite s4 false true))
+[GOOD] (assert s5)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (just_SBVMaybe 0)))
+[SEND] (get-value (s1))
+[RECV] ((s1 (just_SBVMaybe 0)))
+[SEND] (get-value (s2))
+[RECV] ((s2 true))
+
+MODEL: SMTModel {modelObjectives = [], modelBindings = Nothing, modelAssocs = [("s0",Just 0 :: Maybe Integer),("s1",Just 0 :: Maybe Integer),("s2",True :: Bool)], modelUIFuns = []}
+DONE.*** Solver   : Z3
+*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/tuple_enum.gold b/SBVTestSuite/GoldFiles/tuple_enum.gold
--- a/SBVTestSuite/GoldFiles/tuple_enum.gold
+++ b/SBVTestSuite/GoldFiles/tuple_enum.gold
@@ -9,7 +9,7 @@
 [GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
-[GOOD] (declare-datatypes () ((E (A) (B) (C))))
+[GOOD] (declare-datatypes ((E 0)) (((A) (B) (C))))
 [GOOD] (define-fun E_constrIndex ((x E)) Int
           (ite (= x A) 0 (ite (= x B) 1 2))
        )
@@ -17,20 +17,21 @@
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
                                                          (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s6 () Int 1)
-[GOOD] (define-fun s17 () Int 3)
-[GOOD] (define-fun s21 () Int 2)
-[GOOD] (define-fun s32 () Int 6)
-[GOOD] (define-fun s36 () Int 4)
-[GOOD] (define-fun s28 () E C)
-[GOOD] (define-fun s13 () (Seq Bool) (seq.unit true))
+[GOOD] (define-fun s5 () Int 1)
+[GOOD] (define-fun s16 () Int 3)
+[GOOD] (define-fun s20 () Int 2)
+[GOOD] (define-fun s30 () Int 6)
+[GOOD] (define-fun s34 () Int 4)
+[GOOD] (define-fun s26 () E C)
+[GOOD] (define-fun s12 () (Seq Bool) (seq.unit true))
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq (SBVTuple2 E (Seq Bool)))) ; tracks user variable "v1"
 [GOOD] (declare-fun s1 () Bool) ; tracks user variable "q"
 [GOOD] (declare-fun s3 () (SBVTuple2 E (Seq Bool))) ; tracks user variable "__internal_sbv_s3"
-[GOOD] (declare-fun s19 () (SBVTuple2 E (Seq Bool))) ; tracks user variable "__internal_sbv_s19"
-[GOOD] (declare-fun s34 () Bool) ; tracks user variable "__internal_sbv_s34"
+[GOOD] (declare-fun s18 () (SBVTuple2 E (Seq Bool))) ; tracks user variable "__internal_sbv_s18"
+[GOOD] (declare-fun s32 () Bool) ; tracks user variable "__internal_sbv_s32"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -39,54 +40,53 @@
 [GOOD] ; --- formula ---
 [GOOD] (define-fun s2 () Bool (not s1))
 [GOOD] (define-fun s4 () (Seq (SBVTuple2 E (Seq Bool))) (seq.unit s3))
-[GOOD] (define-fun s5 () Int (seq.len s0))
-[GOOD] (define-fun s7 () Bool (> s5 s6))
-[GOOD] (define-fun s8 () Bool (not s7))
-[GOOD] (define-fun s9 () (Seq (SBVTuple2 E (Seq Bool))) (seq.extract s0 s6 s6))
-[GOOD] (define-fun s10 () Bool (= s4 s9))
-[GOOD] (define-fun s11 () Bool (or s8 s10))
-[GOOD] (define-fun s12 () (Seq Bool) (proj_2_SBVTuple2 s3))
-[GOOD] (define-fun s14 () (Seq Bool) (seq.unit s1))
-[GOOD] (define-fun s15 () (Seq Bool) (seq.++ s13 s14))
-[GOOD] (define-fun s16 () Bool (= s12 s15))
-[GOOD] (define-fun s18 () Bool (= s5 s17))
-[GOOD] (define-fun s20 () (Seq (SBVTuple2 E (Seq Bool))) (seq.unit s19))
-[GOOD] (define-fun s22 () Bool (> s5 s21))
-[GOOD] (define-fun s23 () Bool (not s22))
-[GOOD] (define-fun s24 () (Seq (SBVTuple2 E (Seq Bool))) (seq.extract s0 s21 s6))
-[GOOD] (define-fun s25 () Bool (= s20 s24))
-[GOOD] (define-fun s26 () Bool (or s23 s25))
-[GOOD] (define-fun s27 () E (proj_1_SBVTuple2 s19))
-[GOOD] (define-fun s29 () Bool (= s27 s28))
-[GOOD] (define-fun s30 () (Seq Bool) (proj_2_SBVTuple2 s19))
-[GOOD] (define-fun s31 () Int (seq.len s30))
-[GOOD] (define-fun s33 () Bool (= s31 s32))
-[GOOD] (define-fun s35 () (Seq Bool) (seq.unit s34))
-[GOOD] (define-fun s37 () Bool (> s31 s36))
-[GOOD] (define-fun s38 () Bool (not s37))
-[GOOD] (define-fun s39 () (Seq Bool) (seq.extract s30 s36 s6))
-[GOOD] (define-fun s40 () Bool (= s35 s39))
-[GOOD] (define-fun s41 () Bool (or s38 s40))
+[GOOD] (define-fun s6 () (Seq (SBVTuple2 E (Seq Bool))) (seq.extract s0 s5 s5))
+[GOOD] (define-fun s7 () Bool (= s4 s6))
+[GOOD] (define-fun s8 () Int (seq.len s0))
+[GOOD] (define-fun s9 () Bool (<= s8 s5))
+[GOOD] (define-fun s10 () Bool (or s7 s9))
+[GOOD] (define-fun s11 () (Seq Bool) (proj_2_SBVTuple2 s3))
+[GOOD] (define-fun s13 () (Seq Bool) (seq.unit s1))
+[GOOD] (define-fun s14 () (Seq Bool) (seq.++ s12 s13))
+[GOOD] (define-fun s15 () Bool (= s11 s14))
+[GOOD] (define-fun s17 () Bool (= s8 s16))
+[GOOD] (define-fun s19 () (Seq (SBVTuple2 E (Seq Bool))) (seq.unit s18))
+[GOOD] (define-fun s21 () (Seq (SBVTuple2 E (Seq Bool))) (seq.extract s0 s20 s5))
+[GOOD] (define-fun s22 () Bool (= s19 s21))
+[GOOD] (define-fun s23 () Bool (<= s8 s20))
+[GOOD] (define-fun s24 () Bool (or s22 s23))
+[GOOD] (define-fun s25 () E (proj_1_SBVTuple2 s18))
+[GOOD] (define-fun s27 () Bool (= s25 s26))
+[GOOD] (define-fun s28 () (Seq Bool) (proj_2_SBVTuple2 s18))
+[GOOD] (define-fun s29 () Int (seq.len s28))
+[GOOD] (define-fun s31 () Bool (= s29 s30))
+[GOOD] (define-fun s33 () (Seq Bool) (seq.unit s32))
+[GOOD] (define-fun s35 () (Seq Bool) (seq.extract s28 s34 s5))
+[GOOD] (define-fun s36 () Bool (= s33 s35))
+[GOOD] (define-fun s37 () Bool (<= s29 s34))
+[GOOD] (define-fun s38 () Bool (or s36 s37))
 [GOOD] (assert s2)
-[GOOD] (assert s11)
-[GOOD] (assert s16)
-[GOOD] (assert s18)
-[GOOD] (assert s26)
-[GOOD] (assert s29)
-[GOOD] (assert s33)
-[GOOD] (assert s41)
-[GOOD] (assert s34)
+[GOOD] (assert s10)
+[GOOD] (assert s15)
+[GOOD] (assert s17)
+[GOOD] (assert s24)
+[GOOD] (assert s27)
+[GOOD] (assert s31)
+[GOOD] (assert s38)
+[GOOD] (assert s32)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (declare-datatypes ((SBVTuple3 3)) ((par (T1 T2 T3)
                                            ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
                                                          (proj_2_SBVTuple3 T2)
                                                          (proj_3_SBVTuple3 T3))))))
-[GOOD] (declare-fun s42 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E (_ BitVec 8) (_ FloatingPoint  8 24))))
-[GOOD] (define-fun s43 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E (_ BitVec 8) (_ FloatingPoint  8 24))) (mkSBVTuple2 #x05 (mkSBVTuple3 C #x41 ((_ to_fp 8 24) roundNearestTiesToEven (/ 8514437.0 1048576.0)))))
-[GOOD] (define-fun s44 () Bool (= s42 s43))
-[GOOD] (assert s44)
-[GOOD] (define-fun s45 () (Seq (SBVTuple2 E (Seq Bool))) (seq.++ (seq.unit (mkSBVTuple2 B (as seq.empty (Seq Bool)))) (seq.unit (mkSBVTuple2 A (seq.++ (seq.unit true) (seq.unit false)))) (seq.unit (mkSBVTuple2 C (seq.++ (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit true) (seq.unit false))))))
-[GOOD] (define-fun s46 () Bool (= s0 s45))
-[GOOD] (assert s46)
+[GOOD] (declare-fun s39 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E (_ BitVec 8) (_ FloatingPoint  8 24))))
+[GOOD] (define-fun s40 () (SBVTuple2 (_ BitVec 8) (SBVTuple3 E (_ BitVec 8) (_ FloatingPoint  8 24))) (mkSBVTuple2 #x05 (mkSBVTuple3 C #x41 ((_ to_fp 8 24) roundNearestTiesToEven (/ 8514437.0 1048576.0)))))
+[GOOD] (define-fun s41 () Bool (= s39 s40))
+[GOOD] (assert s41)
+[GOOD] (define-fun s42 () (Seq (SBVTuple2 E (Seq Bool))) (seq.++ (seq.unit (mkSBVTuple2 B (as seq.empty (Seq Bool)))) (seq.unit (mkSBVTuple2 A (seq.++ (seq.unit true) (seq.unit false)))) (seq.unit (mkSBVTuple2 C (seq.++ (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit false) (seq.unit true) (seq.unit false))))))
+[GOOD] (define-fun s43 () Bool (= s0 s42))
+[GOOD] (assert s43)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
@@ -100,8 +100,8 @@
                                                                       (seq.++ (seq.unit false)
                                                                               (seq.++ (seq.unit true)
                                                                                       (seq.unit false))))))))))))
-[SEND] (get-value (s42))
-[RECV] ((s42 (mkSBVTuple2 #x05 (mkSBVTuple3 C #x41 (fp #b0 #x82 #b00000011110101110000101)))))
+[SEND] (get-value (s39))
+[RECV] ((s39 (mkSBVTuple2 #x05 (mkSBVTuple3 C #x41 (fp #b0 #x82 #b00000011110101110000101)))))
 *** Solver   : Z3
 *** Exit code: ExitSuccess
 
diff --git a/SBVTestSuite/GoldFiles/tuple_list.gold b/SBVTestSuite/GoldFiles/tuple_list.gold
--- a/SBVTestSuite/GoldFiles/tuple_list.gold
+++ b/SBVTestSuite/GoldFiles/tuple_list.gold
@@ -13,21 +13,22 @@
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
                                                          (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
-[GOOD] (define-fun s4 () Int 0)
-[GOOD] (define-fun s7 () Int 1)
-[GOOD] (define-fun s12 () Int 2)
-[GOOD] (define-fun s33 () Int 4)
-[GOOD] (define-fun s41 () Int 5)
-[GOOD] (define-fun s31 () String "foo")
-[GOOD] (define-fun s53 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.++ (seq.unit (mkSBVTuple2 2 (as seq.empty (Seq (SBVTuple2 Int String))))) (seq.unit (mkSBVTuple2 1 (seq.++ (seq.unit (mkSBVTuple2 3 "foo")) (seq.unit (mkSBVTuple2 0 "bar")) (seq.unit (mkSBVTuple2 (- 1) "baz")) (seq.unit (mkSBVTuple2 (- 2) "quux")) (seq.unit (mkSBVTuple2 (- 3) "enough"))))) (seq.unit (mkSBVTuple2 (- 4) (as seq.empty (Seq (SBVTuple2 Int String))))) (seq.unit (mkSBVTuple2 (- 5) (as seq.empty (Seq (SBVTuple2 Int String)))))))
+[GOOD] (define-fun s3 () Int 0)
+[GOOD] (define-fun s4 () Int 1)
+[GOOD] (define-fun s11 () Int 2)
+[GOOD] (define-fun s30 () Int 4)
+[GOOD] (define-fun s38 () Int 5)
+[GOOD] (define-fun s28 () String "foo")
+[GOOD] (define-fun s49 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.++ (seq.unit (mkSBVTuple2 2 (as seq.empty (Seq (SBVTuple2 Int String))))) (seq.unit (mkSBVTuple2 1 (seq.++ (seq.unit (mkSBVTuple2 3 "foo")) (seq.unit (mkSBVTuple2 0 "bar")) (seq.unit (mkSBVTuple2 (- 1) "baz")) (seq.unit (mkSBVTuple2 (- 2) "quux")) (seq.unit (mkSBVTuple2 (- 3) "enough"))))) (seq.unit (mkSBVTuple2 (- 4) (as seq.empty (Seq (SBVTuple2 Int String))))) (seq.unit (mkSBVTuple2 (- 5) (as seq.empty (Seq (SBVTuple2 Int String)))))))
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String))))) ; tracks user variable "lst"
 [GOOD] (declare-fun s1 () (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) ; tracks user variable "__internal_sbv_s1"
-[GOOD] (declare-fun s14 () (SBVTuple2 Int String)) ; tracks user variable "__internal_sbv_s14"
-[GOOD] (declare-fun s16 () (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) ; tracks user variable "__internal_sbv_s16"
-[GOOD] (declare-fun s35 () (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) ; tracks user variable "__internal_sbv_s35"
-[GOOD] (declare-fun s43 () (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) ; tracks user variable "__internal_sbv_s43"
+[GOOD] (declare-fun s13 () (SBVTuple2 Int String)) ; tracks user variable "__internal_sbv_s13"
+[GOOD] (declare-fun s15 () (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) ; tracks user variable "__internal_sbv_s15"
+[GOOD] (declare-fun s32 () (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) ; tracks user variable "__internal_sbv_s32"
+[GOOD] (declare-fun s40 () (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) ; tracks user variable "__internal_sbv_s40"
 [GOOD] ; --- constant tables ---
 [GOOD] ; --- skolemized tables ---
 [GOOD] ; --- arrays ---
@@ -35,58 +36,54 @@
 [GOOD] ; --- user given axioms ---
 [GOOD] ; --- formula ---
 [GOOD] (define-fun s2 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.unit s1))
-[GOOD] (define-fun s3 () Int (seq.len s0))
-[GOOD] (define-fun s5 () Bool (> s3 s4))
-[GOOD] (define-fun s6 () Bool (not s5))
-[GOOD] (define-fun s8 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.extract s0 s4 s7))
-[GOOD] (define-fun s9 () Bool (= s2 s8))
-[GOOD] (define-fun s10 () Bool (or s6 s9))
-[GOOD] (define-fun s11 () Int (proj_1_SBVTuple2 s1))
-[GOOD] (define-fun s13 () Bool (= s11 s12))
-[GOOD] (define-fun s15 () (Seq (SBVTuple2 Int String)) (seq.unit s14))
-[GOOD] (define-fun s17 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.unit s16))
-[GOOD] (define-fun s18 () Bool (> s3 s7))
-[GOOD] (define-fun s19 () Bool (not s18))
-[GOOD] (define-fun s20 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.extract s0 s7 s7))
-[GOOD] (define-fun s21 () Bool (= s17 s20))
-[GOOD] (define-fun s22 () Bool (or s19 s21))
-[GOOD] (define-fun s23 () (Seq (SBVTuple2 Int String)) (proj_2_SBVTuple2 s16))
-[GOOD] (define-fun s24 () Int (seq.len s23))
-[GOOD] (define-fun s25 () Bool (> s24 s4))
-[GOOD] (define-fun s26 () Bool (not s25))
-[GOOD] (define-fun s27 () (Seq (SBVTuple2 Int String)) (seq.extract s23 s4 s7))
-[GOOD] (define-fun s28 () Bool (= s15 s27))
-[GOOD] (define-fun s29 () Bool (or s26 s28))
-[GOOD] (define-fun s30 () String (proj_2_SBVTuple2 s14))
-[GOOD] (define-fun s32 () Bool (= s30 s31))
-[GOOD] (define-fun s34 () Bool (= s3 s33))
-[GOOD] (define-fun s36 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.unit s35))
-[GOOD] (define-fun s37 () Bool (= s20 s36))
-[GOOD] (define-fun s38 () Bool (or s19 s37))
-[GOOD] (define-fun s39 () (Seq (SBVTuple2 Int String)) (proj_2_SBVTuple2 s35))
-[GOOD] (define-fun s40 () Int (seq.len s39))
-[GOOD] (define-fun s42 () Bool (= s40 s41))
-[GOOD] (define-fun s44 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.unit s43))
-[GOOD] (define-fun s45 () Bool (> s3 s12))
-[GOOD] (define-fun s46 () Bool (not s45))
-[GOOD] (define-fun s47 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.extract s0 s12 s7))
-[GOOD] (define-fun s48 () Bool (= s44 s47))
-[GOOD] (define-fun s49 () Bool (or s46 s48))
-[GOOD] (define-fun s50 () (Seq (SBVTuple2 Int String)) (proj_2_SBVTuple2 s43))
-[GOOD] (define-fun s51 () Int (seq.len s50))
-[GOOD] (define-fun s52 () Bool (= s4 s51))
-[GOOD] (define-fun s54 () Bool (= s0 s53))
-[GOOD] (assert s10)
-[GOOD] (assert s13)
-[GOOD] (assert s22)
+[GOOD] (define-fun s5 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.extract s0 s3 s4))
+[GOOD] (define-fun s6 () Bool (= s2 s5))
+[GOOD] (define-fun s7 () Int (seq.len s0))
+[GOOD] (define-fun s8 () Bool (<= s7 s3))
+[GOOD] (define-fun s9 () Bool (or s6 s8))
+[GOOD] (define-fun s10 () Int (proj_1_SBVTuple2 s1))
+[GOOD] (define-fun s12 () Bool (= s10 s11))
+[GOOD] (define-fun s14 () (Seq (SBVTuple2 Int String)) (seq.unit s13))
+[GOOD] (define-fun s16 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.unit s15))
+[GOOD] (define-fun s17 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.extract s0 s4 s4))
+[GOOD] (define-fun s18 () Bool (= s16 s17))
+[GOOD] (define-fun s19 () Bool (<= s7 s4))
+[GOOD] (define-fun s20 () Bool (or s18 s19))
+[GOOD] (define-fun s21 () (Seq (SBVTuple2 Int String)) (proj_2_SBVTuple2 s15))
+[GOOD] (define-fun s22 () (Seq (SBVTuple2 Int String)) (seq.extract s21 s3 s4))
+[GOOD] (define-fun s23 () Bool (= s14 s22))
+[GOOD] (define-fun s24 () Int (seq.len s21))
+[GOOD] (define-fun s25 () Bool (<= s24 s3))
+[GOOD] (define-fun s26 () Bool (or s23 s25))
+[GOOD] (define-fun s27 () String (proj_2_SBVTuple2 s13))
+[GOOD] (define-fun s29 () Bool (= s27 s28))
+[GOOD] (define-fun s31 () Bool (= s7 s30))
+[GOOD] (define-fun s33 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.unit s32))
+[GOOD] (define-fun s34 () Bool (= s17 s33))
+[GOOD] (define-fun s35 () Bool (or s19 s34))
+[GOOD] (define-fun s36 () (Seq (SBVTuple2 Int String)) (proj_2_SBVTuple2 s32))
+[GOOD] (define-fun s37 () Int (seq.len s36))
+[GOOD] (define-fun s39 () Bool (= s37 s38))
+[GOOD] (define-fun s41 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.unit s40))
+[GOOD] (define-fun s42 () (Seq (SBVTuple2 Int (Seq (SBVTuple2 Int String)))) (seq.extract s0 s11 s4))
+[GOOD] (define-fun s43 () Bool (= s41 s42))
+[GOOD] (define-fun s44 () Bool (<= s7 s11))
+[GOOD] (define-fun s45 () Bool (or s43 s44))
+[GOOD] (define-fun s46 () (Seq (SBVTuple2 Int String)) (proj_2_SBVTuple2 s40))
+[GOOD] (define-fun s47 () Int (seq.len s46))
+[GOOD] (define-fun s48 () Bool (= s3 s47))
+[GOOD] (define-fun s50 () Bool (= s0 s49))
+[GOOD] (assert s9)
+[GOOD] (assert s12)
+[GOOD] (assert s20)
+[GOOD] (assert s26)
 [GOOD] (assert s29)
-[GOOD] (assert s32)
-[GOOD] (assert s34)
-[GOOD] (assert s38)
-[GOOD] (assert s42)
-[GOOD] (assert s49)
-[GOOD] (assert s52)
-[GOOD] (assert s54)
+[GOOD] (assert s31)
+[GOOD] (assert s35)
+[GOOD] (assert s39)
+[GOOD] (assert s45)
+[GOOD] (assert s48)
+[GOOD] (assert s50)
 [SEND] (check-sat)
 [RECV] sat
 [SEND] (get-value (s0))
diff --git a/SBVTestSuite/GoldFiles/tuple_nested.gold b/SBVTestSuite/GoldFiles/tuple_nested.gold
--- a/SBVTestSuite/GoldFiles/tuple_nested.gold
+++ b/SBVTestSuite/GoldFiles/tuple_nested.gold
@@ -5,12 +5,15 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
                                                          (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s13 () (_ BitVec 8) #x00)
 [GOOD] (define-fun s3 () Int 1)
diff --git a/SBVTestSuite/GoldFiles/tuple_swap.gold b/SBVTestSuite/GoldFiles/tuple_swap.gold
--- a/SBVTestSuite/GoldFiles/tuple_swap.gold
+++ b/SBVTestSuite/GoldFiles/tuple_swap.gold
@@ -5,6 +5,8 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
@@ -12,6 +14,7 @@
                                            ((mkSBVTuple3 (proj_1_SBVTuple3 T1)
                                                          (proj_2_SBVTuple3 T2)
                                                          (proj_3_SBVTuple3 T3))))))
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] ; --- skolem constants ---
 [GOOD] (declare-fun s0 () (SBVTuple3 Int Int Int)) ; tracks user variable "abx"
diff --git a/SBVTestSuite/GoldFiles/tuple_twoTwo.gold b/SBVTestSuite/GoldFiles/tuple_twoTwo.gold
--- a/SBVTestSuite/GoldFiles/tuple_twoTwo.gold
+++ b/SBVTestSuite/GoldFiles/tuple_twoTwo.gold
@@ -5,12 +5,15 @@
 [GOOD] (set-option :smtlib2_compliant true)
 [GOOD] (set-option :diagnostic-output-channel "stdout")
 [GOOD] (set-option :produce-models true)
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
 [GOOD] (set-logic ALL)
 [GOOD] ; --- uninterpreted sorts ---
 [GOOD] ; --- tuples ---
 [GOOD] (declare-datatypes ((SBVTuple2 2)) ((par (T1 T2)
                                            ((mkSBVTuple2 (proj_1_SBVTuple2 T1)
                                                          (proj_2_SBVTuple2 T2))))))
+[GOOD] ; --- sums ---
 [GOOD] ; --- literal constants ---
 [GOOD] (define-fun s3 () Int 1)
 [GOOD] (define-fun s6 () (_ BitVec 8) #x63)
diff --git a/SBVTestSuite/GoldFiles/uiSat_test1.gold b/SBVTestSuite/GoldFiles/uiSat_test1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/uiSat_test1.gold
@@ -0,0 +1,103 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; NB. User specified.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q1 (Bool) Bool)
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s0 () Bool (q1 false))
+*** Checking Satisfiability, all solutions..
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[GOOD] (define-fun q1_model1 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model1_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model1 x!0))))
+[GOOD] (define-fun uiFunRejector_model_1 () Bool q1_model1_reject)
+[GOOD] (assert uiFunRejector_model_1)
+Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[GOOD] (define-fun q1_model2 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model2_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model2 x!0))))
+[GOOD] (define-fun uiFunRejector_model_2 () Bool q1_model2_reject)
+[GOOD] (assert uiFunRejector_model_2)
+Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[GOOD] (define-fun q1_model3 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model3_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model3 x!0))))
+[GOOD] (define-fun uiFunRejector_model_3 () Bool q1_model3_reject)
+[GOOD] (assert uiFunRejector_model_3)
+Looking for solution 4
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[GOOD] (define-fun q1_model4 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model4_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model4 x!0))))
+[GOOD] (define-fun uiFunRejector_model_4 () Bool q1_model4_reject)
+[GOOD] (assert uiFunRejector_model_4)
+Looking for solution 5
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Solution #1:
+  q1 :: Bool -> Bool
+  q1 _ = False
+Solution #2:
+  q1 :: Bool -> Bool
+  q1 _ = True
+Solution #3:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+Solution #4:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+Found 4 different solutions.
diff --git a/SBVTestSuite/GoldFiles/uiSat_test2.gold b/SBVTestSuite/GoldFiles/uiSat_test2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/uiSat_test2.gold
@@ -0,0 +1,426 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; NB. User specified.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q2 (Bool Bool) Bool)
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s0 () Bool (q2 false false))
+*** Checking Satisfiability, all solutions..
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) false)))
+[GOOD] (define-fun q2_model1 ((x!0 Bool) (x!1 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q2_model1_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model1 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_1 () Bool q2_model1_reject)
+[GOOD] (assert uiFunRejector_model_1)
+Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) true)))
+[GOOD] (define-fun q2_model2 ((x!0 Bool) (x!1 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q2_model2_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model2 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_2 () Bool q2_model2_reject)
+[GOOD] (assert uiFunRejector_model_2)
+Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q2_model3 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model3_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model3 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_3 () Bool q2_model3_reject)
+[GOOD] (assert uiFunRejector_model_3)
+Looking for solution 4
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) x!2))))
+[GOOD] (define-fun q2_model4 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model4_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model4 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_4 () Bool q2_model4_reject)
+[GOOD] (assert uiFunRejector_model_4)
+Looking for solution 5
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 x!2))))
+[GOOD] (define-fun q2_model5 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model5_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model5 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_5 () Bool q2_model5_reject)
+[GOOD] (assert uiFunRejector_model_5)
+Looking for solution 6
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 (not x!2)) (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q2_model6 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model6_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model6 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_6 () Bool q2_model6_reject)
+[GOOD] (assert uiFunRejector_model_6)
+Looking for solution 7
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 (not x!2)))))
+[GOOD] (define-fun q2_model7 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model7_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model7 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_7 () Bool q2_model7_reject)
+[GOOD] (assert uiFunRejector_model_7)
+Looking for solution 8
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and (not x!1) x!2) (and x!1 (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q2_model8 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model8_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model8 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_8 () Bool q2_model8_reject)
+[GOOD] (assert uiFunRejector_model_8)
+Looking for solution 9
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and (not x!1) x!2) (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q2_model9 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model9_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model9 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_9 () Bool q2_model9_reject)
+[GOOD] (assert uiFunRejector_model_9)
+Looking for solution 10
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) (not x!2)))))
+[GOOD] (define-fun q2_model10 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model10_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model10 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_10 () Bool q2_model10_reject)
+[GOOD] (assert uiFunRejector_model_10)
+Looking for solution 11
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q2_model11 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model11_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model11 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_11 () Bool q2_model11_reject)
+[GOOD] (assert uiFunRejector_model_11)
+Looking for solution 12
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 (not x!2))) (not (and (not x!1) x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q2_model12 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model12_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model12 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_12 () Bool q2_model12_reject)
+[GOOD] (assert uiFunRejector_model_12)
+Looking for solution 13
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (or (and x!1 (not x!2)) (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q2_model13 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model13_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model13 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_13 () Bool q2_model13_reject)
+[GOOD] (assert uiFunRejector_model_13)
+Looking for solution 14
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 (not x!2))) (not (and x!1 x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q2_model14 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model14_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model14 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_14 () Bool q2_model14_reject)
+[GOOD] (assert uiFunRejector_model_14)
+Looking for solution 15
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q2_model15 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model15_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model15 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_15 () Bool q2_model15_reject)
+[GOOD] (assert uiFunRejector_model_15)
+Looking for solution 16
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q2_model16 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model16_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model16 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_16 () Bool q2_model16_reject)
+[GOOD] (assert uiFunRejector_model_16)
+Looking for solution 17
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Solution #1:
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Solution #2:
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #3:
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True 
+Solution #4:
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 _     _    = False
+Solution #5:
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True 
+  q2 _    _    = False
+Solution #6:
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 True True  = True 
+  q2 _    _     = False
+Solution #7:
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 _    _     = False
+Solution #8:
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #9:
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 True  True = True 
+  q2 _     _    = False
+Solution #10:
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 _     _     = False
+Solution #11:
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True 
+Solution #12:
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  True  = True 
+  q2 _     _     = False
+Solution #13:
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #14:
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 False True  = True 
+  q2 _     _     = False
+Solution #15:
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True 
+Solution #16:
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True 
+Found 16 different solutions.
diff --git a/SBVTestSuite/GoldFiles/uiSat_test3.gold b/SBVTestSuite/GoldFiles/uiSat_test3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/uiSat_test3.gold
@@ -0,0 +1,2638 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; NB. User specified.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] (declare-fun q1 (Bool) Bool)
+[GOOD] (declare-fun q2 (Bool Bool) Bool)
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s0 () Bool (q1 false))
+[GOOD] (define-fun s1 () Bool (q2 false false))
+*** Checking Satisfiability, all solutions..
+[GOOD] (set-option :pp.max_depth      4294967295)
+[GOOD] (set-option :pp.min_alias_size 4294967295)
+Looking for solution 1
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) false)))
+[GOOD] (define-fun q1_model1 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model1_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model1 x!0))))
+[GOOD] (define-fun q2_model1 ((x!0 Bool) (x!1 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q2_model1_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model1 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_1 () Bool 
+               (or q1_model1_reject
+                   q2_model1_reject
+               ))
+[GOOD] (assert uiFunRejector_model_1)
+Looking for solution 2
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) false)))
+[GOOD] (define-fun q1_model2 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model2_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model2 x!0))))
+[GOOD] (define-fun q2_model2 ((x!0 Bool) (x!1 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q2_model2_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model2 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_2 () Bool 
+               (or q1_model2_reject
+                   q2_model2_reject
+               ))
+[GOOD] (assert uiFunRejector_model_2)
+Looking for solution 3
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) true)))
+[GOOD] (define-fun q1_model3 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model3_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model3 x!0))))
+[GOOD] (define-fun q2_model3 ((x!0 Bool) (x!1 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q2_model3_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model3 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_3 () Bool 
+               (or q1_model3_reject
+                   q2_model3_reject
+               ))
+[GOOD] (assert uiFunRejector_model_3)
+Looking for solution 4
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model4 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model4_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model4 x!0))))
+[GOOD] (define-fun q2_model4 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model4_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model4 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_4 () Bool 
+               (or q1_model4_reject
+                   q2_model4_reject
+               ))
+[GOOD] (assert uiFunRejector_model_4)
+Looking for solution 5
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model5 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model5_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model5 x!0))))
+[GOOD] (define-fun q2_model5 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model5_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model5 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_5 () Bool 
+               (or q1_model5_reject
+                   q2_model5_reject
+               ))
+[GOOD] (assert uiFunRejector_model_5)
+Looking for solution 6
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) (not x!2)))))
+[GOOD] (define-fun q1_model6 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model6_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model6 x!0))))
+[GOOD] (define-fun q2_model6 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model6_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model6 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_6 () Bool 
+               (or q1_model6_reject
+                   q2_model6_reject
+               ))
+[GOOD] (assert uiFunRejector_model_6)
+Looking for solution 7
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 x!2) (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model7 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model7_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model7 x!0))))
+[GOOD] (define-fun q2_model7 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model7_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model7 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_7 () Bool 
+               (or q1_model7_reject
+                   q2_model7_reject
+               ))
+[GOOD] (assert uiFunRejector_model_7)
+Looking for solution 8
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model8 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model8_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model8 x!0))))
+[GOOD] (define-fun q2_model8 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model8_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model8 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_8 () Bool 
+               (or q1_model8_reject
+                   q2_model8_reject
+               ))
+[GOOD] (assert uiFunRejector_model_8)
+Looking for solution 9
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model9 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model9_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1        x!0)
+                            (q1_model9 x!0))))
+[GOOD] (define-fun q2_model9 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model9_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2        x!0 x!1)
+                            (q2_model9 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_9 () Bool 
+               (or q1_model9_reject
+                   q2_model9_reject
+               ))
+[GOOD] (assert uiFunRejector_model_9)
+Looking for solution 10
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 x!2)) (not (and (not x!1) x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model10 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model10_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model10 x!0))))
+[GOOD] (define-fun q2_model10 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model10_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model10 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_10 () Bool 
+               (or q1_model10_reject
+                   q2_model10_reject
+               ))
+[GOOD] (assert uiFunRejector_model_10)
+Looking for solution 11
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 x!2)) (not (and (not x!1) x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model11 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model11_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model11 x!0))))
+[GOOD] (define-fun q2_model11 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model11_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model11 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_11 () Bool 
+               (or q1_model11_reject
+                   q2_model11_reject
+               ))
+[GOOD] (assert uiFunRejector_model_11)
+Looking for solution 12
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 x!2)) (not (and (not x!1) x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model12 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model12_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model12 x!0))))
+[GOOD] (define-fun q2_model12 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model12_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model12 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_12 () Bool 
+               (or q1_model12_reject
+                   q2_model12_reject
+               ))
+[GOOD] (assert uiFunRejector_model_12)
+Looking for solution 13
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 x!2)) (not (and (not x!1) x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model13 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model13_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model13 x!0))))
+[GOOD] (define-fun q2_model13 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model13_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model13 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_13 () Bool 
+               (or q1_model13_reject
+                   q2_model13_reject
+               ))
+[GOOD] (assert uiFunRejector_model_13)
+Looking for solution 14
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model14 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model14_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model14 x!0))))
+[GOOD] (define-fun q2_model14 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model14_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model14 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_14 () Bool 
+               (or q1_model14_reject
+                   q2_model14_reject
+               ))
+[GOOD] (assert uiFunRejector_model_14)
+Looking for solution 15
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model15 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model15_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model15 x!0))))
+[GOOD] (define-fun q2_model15 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model15_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model15 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_15 () Bool 
+               (or q1_model15_reject
+                   q2_model15_reject
+               ))
+[GOOD] (assert uiFunRejector_model_15)
+Looking for solution 16
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model16 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model16_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model16 x!0))))
+[GOOD] (define-fun q2_model16 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model16_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model16 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_16 () Bool 
+               (or q1_model16_reject
+                   q2_model16_reject
+               ))
+[GOOD] (assert uiFunRejector_model_16)
+Looking for solution 17
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model17 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model17_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model17 x!0))))
+[GOOD] (define-fun q2_model17 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model17_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model17 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_17 () Bool 
+               (or q1_model17_reject
+                   q2_model17_reject
+               ))
+[GOOD] (assert uiFunRejector_model_17)
+Looking for solution 18
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) true)))
+[GOOD] (define-fun q1_model18 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model18_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model18 x!0))))
+[GOOD] (define-fun q2_model18 ((x!0 Bool) (x!1 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q2_model18_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model18 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_18 () Bool 
+               (or q1_model18_reject
+                   q2_model18_reject
+               ))
+[GOOD] (assert uiFunRejector_model_18)
+Looking for solution 19
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) true)))
+[GOOD] (define-fun q1_model19 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model19_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model19 x!0))))
+[GOOD] (define-fun q2_model19 ((x!0 Bool) (x!1 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q2_model19_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model19 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_19 () Bool 
+               (or q1_model19_reject
+                   q2_model19_reject
+               ))
+[GOOD] (assert uiFunRejector_model_19)
+Looking for solution 20
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) true)))
+[GOOD] (define-fun q1_model20 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model20_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model20 x!0))))
+[GOOD] (define-fun q2_model20 ((x!0 Bool) (x!1 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q2_model20_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model20 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_20 () Bool 
+               (or q1_model20_reject
+                   q2_model20_reject
+               ))
+[GOOD] (assert uiFunRejector_model_20)
+Looking for solution 21
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model21 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model21_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model21 x!0))))
+[GOOD] (define-fun q2_model21 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model21_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model21 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_21 () Bool 
+               (or q1_model21_reject
+                   q2_model21_reject
+               ))
+[GOOD] (assert uiFunRejector_model_21)
+Looking for solution 22
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model22 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model22_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model22 x!0))))
+[GOOD] (define-fun q2_model22 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) false
+          true)
+       )
+[GOOD] (define-fun q2_model22_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model22 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_22 () Bool 
+               (or q1_model22_reject
+                   q2_model22_reject
+               ))
+[GOOD] (assert uiFunRejector_model_22)
+Looking for solution 23
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model23 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model23_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model23 x!0))))
+[GOOD] (define-fun q2_model23 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model23_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model23 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_23 () Bool 
+               (or q1_model23_reject
+                   q2_model23_reject
+               ))
+[GOOD] (assert uiFunRejector_model_23)
+Looking for solution 24
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) false)))
+[GOOD] (define-fun q1_model24 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model24_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model24 x!0))))
+[GOOD] (define-fun q2_model24 ((x!0 Bool) (x!1 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q2_model24_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model24 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_24 () Bool 
+               (or q1_model24_reject
+                   q2_model24_reject
+               ))
+[GOOD] (assert uiFunRejector_model_24)
+Looking for solution 25
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 (not x!2)))))
+[GOOD] (define-fun q1_model25 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model25_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model25 x!0))))
+[GOOD] (define-fun q2_model25 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model25_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model25 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_25 () Bool 
+               (or q1_model25_reject
+                   q2_model25_reject
+               ))
+[GOOD] (assert uiFunRejector_model_25)
+Looking for solution 26
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model26 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model26_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model26 x!0))))
+[GOOD] (define-fun q2_model26 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model26_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model26 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_26 () Bool 
+               (or q1_model26_reject
+                   q2_model26_reject
+               ))
+[GOOD] (assert uiFunRejector_model_26)
+Looking for solution 27
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and (not x!1) x!2)) (not (and (not x!1) (not x!2)))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model27 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model27_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model27 x!0))))
+[GOOD] (define-fun q2_model27 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model27_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model27 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_27 () Bool 
+               (or q1_model27_reject
+                   q2_model27_reject
+               ))
+[GOOD] (assert uiFunRejector_model_27)
+Looking for solution 28
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) x!2))))
+[GOOD] (define-fun q1_model28 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model28_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model28 x!0))))
+[GOOD] (define-fun q2_model28 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model28_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model28 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_28 () Bool 
+               (or q1_model28_reject
+                   q2_model28_reject
+               ))
+[GOOD] (assert uiFunRejector_model_28)
+Looking for solution 29
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 x!2))))
+[GOOD] (define-fun q1_model29 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model29_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model29 x!0))))
+[GOOD] (define-fun q2_model29 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model29_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model29 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_29 () Bool 
+               (or q1_model29_reject
+                   q2_model29_reject
+               ))
+[GOOD] (assert uiFunRejector_model_29)
+Looking for solution 30
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 (not x!2)))))
+[GOOD] (define-fun q1_model30 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model30_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model30 x!0))))
+[GOOD] (define-fun q2_model30 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model30_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model30 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_30 () Bool 
+               (or q1_model30_reject
+                   q2_model30_reject
+               ))
+[GOOD] (assert uiFunRejector_model_30)
+Looking for solution 31
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) x!2))))
+[GOOD] (define-fun q1_model31 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model31_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model31 x!0))))
+[GOOD] (define-fun q2_model31 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model31_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model31 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_31 () Bool 
+               (or q1_model31_reject
+                   q2_model31_reject
+               ))
+[GOOD] (assert uiFunRejector_model_31)
+Looking for solution 32
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 x!2) (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model32 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model32_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model32 x!0))))
+[GOOD] (define-fun q2_model32 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model32_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model32 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_32 () Bool 
+               (or q1_model32_reject
+                   q2_model32_reject
+               ))
+[GOOD] (assert uiFunRejector_model_32)
+Looking for solution 33
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 (not x!2)) (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model33 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model33_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model33 x!0))))
+[GOOD] (define-fun q2_model33 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model33_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model33 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_33 () Bool 
+               (or q1_model33_reject
+                   q2_model33_reject
+               ))
+[GOOD] (assert uiFunRejector_model_33)
+Looking for solution 34
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 x!2))))
+[GOOD] (define-fun q1_model34 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model34_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model34 x!0))))
+[GOOD] (define-fun q2_model34 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model34_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model34 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_34 () Bool 
+               (or q1_model34_reject
+                   q2_model34_reject
+               ))
+[GOOD] (assert uiFunRejector_model_34)
+Looking for solution 35
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 (not x!2)) (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model35 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model35_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model35 x!0))))
+[GOOD] (define-fun q2_model35 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model35_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model35 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_35 () Bool 
+               (or q1_model35_reject
+                   q2_model35_reject
+               ))
+[GOOD] (assert uiFunRejector_model_35)
+Looking for solution 36
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and (not x!1) x!2) (and x!1 x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model36 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model36_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model36 x!0))))
+[GOOD] (define-fun q2_model36 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model36_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model36 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_36 () Bool 
+               (or q1_model36_reject
+                   q2_model36_reject
+               ))
+[GOOD] (assert uiFunRejector_model_36)
+Looking for solution 37
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) x!2))))
+[GOOD] (define-fun q1_model37 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model37_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model37 x!0))))
+[GOOD] (define-fun q2_model37 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model37_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model37 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_37 () Bool 
+               (or q1_model37_reject
+                   q2_model37_reject
+               ))
+[GOOD] (assert uiFunRejector_model_37)
+Looking for solution 38
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model38 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model38_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model38 x!0))))
+[GOOD] (define-fun q2_model38 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model38_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model38 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_38 () Bool 
+               (or q1_model38_reject
+                   q2_model38_reject
+               ))
+[GOOD] (assert uiFunRejector_model_38)
+Looking for solution 39
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 x!2)) (not (and (not x!1) (not x!2)))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model39 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model39_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model39 x!0))))
+[GOOD] (define-fun q2_model39 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model39_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model39 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_39 () Bool 
+               (or q1_model39_reject
+                   q2_model39_reject
+               ))
+[GOOD] (assert uiFunRejector_model_39)
+Looking for solution 40
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 x!2)) (not (and (not x!1) (not x!2)))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model40 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model40_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model40 x!0))))
+[GOOD] (define-fun q2_model40 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model40_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model40 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_40 () Bool 
+               (or q1_model40_reject
+                   q2_model40_reject
+               ))
+[GOOD] (assert uiFunRejector_model_40)
+Looking for solution 41
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model41 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model41_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model41 x!0))))
+[GOOD] (define-fun q2_model41 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model41_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model41 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_41 () Bool 
+               (or q1_model41_reject
+                   q2_model41_reject
+               ))
+[GOOD] (assert uiFunRejector_model_41)
+Looking for solution 42
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) x!2))))
+[GOOD] (define-fun q1_model42 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model42_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model42 x!0))))
+[GOOD] (define-fun q2_model42 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model42_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model42 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_42 () Bool 
+               (or q1_model42_reject
+                   q2_model42_reject
+               ))
+[GOOD] (assert uiFunRejector_model_42)
+Looking for solution 43
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 x!2) (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model43 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model43_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model43 x!0))))
+[GOOD] (define-fun q2_model43 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model43_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model43 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_43 () Bool 
+               (or q1_model43_reject
+                   q2_model43_reject
+               ))
+[GOOD] (assert uiFunRejector_model_43)
+Looking for solution 44
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 (not x!2))) (not (and (not x!1) (not x!2)))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model44 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model44_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model44 x!0))))
+[GOOD] (define-fun q2_model44 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model44_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model44 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_44 () Bool 
+               (or q1_model44_reject
+                   q2_model44_reject
+               ))
+[GOOD] (assert uiFunRejector_model_44)
+Looking for solution 45
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model45 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model45_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model45 x!0))))
+[GOOD] (define-fun q2_model45 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model45_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model45 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_45 () Bool 
+               (or q1_model45_reject
+                   q2_model45_reject
+               ))
+[GOOD] (assert uiFunRejector_model_45)
+Looking for solution 46
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (not (and x!1 (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model46 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model46_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model46 x!0))))
+[GOOD] (define-fun q2_model46 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) false
+          true)
+       )
+[GOOD] (define-fun q2_model46_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model46 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_46 () Bool 
+               (or q1_model46_reject
+                   q2_model46_reject
+               ))
+[GOOD] (assert uiFunRejector_model_46)
+Looking for solution 47
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and x!1 x!2)) (not (and x!1 (not x!2)))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model47 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model47_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model47 x!0))))
+[GOOD] (define-fun q2_model47 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model47_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model47 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_47 () Bool 
+               (or q1_model47_reject
+                   q2_model47_reject
+               ))
+[GOOD] (assert uiFunRejector_model_47)
+Looking for solution 48
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) (not x!2)))))
+[GOOD] (define-fun q1_model48 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model48_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model48 x!0))))
+[GOOD] (define-fun q2_model48 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model48_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model48 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_48 () Bool 
+               (or q1_model48_reject
+                   q2_model48_reject
+               ))
+[GOOD] (assert uiFunRejector_model_48)
+Looking for solution 49
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 x!2) (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model49 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model49_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model49 x!0))))
+[GOOD] (define-fun q2_model49 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model49_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model49 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_49 () Bool 
+               (or q1_model49_reject
+                   q2_model49_reject
+               ))
+[GOOD] (assert uiFunRejector_model_49)
+Looking for solution 50
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 x!2) (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model50 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model50_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model50 x!0))))
+[GOOD] (define-fun q2_model50 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model50_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model50 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_50 () Bool 
+               (or q1_model50_reject
+                   q2_model50_reject
+               ))
+[GOOD] (assert uiFunRejector_model_50)
+Looking for solution 51
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) (not x!2)))))
+[GOOD] (define-fun q1_model51 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model51_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model51 x!0))))
+[GOOD] (define-fun q2_model51 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model51_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model51 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_51 () Bool 
+               (or q1_model51_reject
+                   q2_model51_reject
+               ))
+[GOOD] (assert uiFunRejector_model_51)
+Looking for solution 52
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (or (and (not x!1) x!2) (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model52 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model52_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model52 x!0))))
+[GOOD] (define-fun q2_model52 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model52_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model52 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_52 () Bool 
+               (or q1_model52_reject
+                   q2_model52_reject
+               ))
+[GOOD] (assert uiFunRejector_model_52)
+Looking for solution 53
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 x!2))))
+[GOOD] (define-fun q1_model53 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model53_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model53 x!0))))
+[GOOD] (define-fun q2_model53 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model53_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model53 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_53 () Bool 
+               (or q1_model53_reject
+                   q2_model53_reject
+               ))
+[GOOD] (assert uiFunRejector_model_53)
+Looking for solution 54
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (and (not (and (not x!1) (not x!2))) (not (and x!1 x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model54 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model54_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model54 x!0))))
+[GOOD] (define-fun q2_model54 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 true)) true
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false))
+       )
+[GOOD] (define-fun q2_model54_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model54 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_54 () Bool 
+               (or q1_model54_reject
+                   q2_model54_reject
+               ))
+[GOOD] (assert uiFunRejector_model_54)
+Looking for solution 55
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 x!2))))
+[GOOD] (define-fun q1_model55 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model55_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model55 x!0))))
+[GOOD] (define-fun q2_model55 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false)
+       )
+[GOOD] (define-fun q2_model55_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model55 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_55 () Bool 
+               (or q1_model55_reject
+                   q2_model55_reject
+               ))
+[GOOD] (assert uiFunRejector_model_55)
+Looking for solution 56
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 (not x!2)))))
+[GOOD] (define-fun q1_model56 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model56_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model56 x!0))))
+[GOOD] (define-fun q2_model56 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model56_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model56 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_56 () Bool 
+               (or q1_model56_reject
+                   q2_model56_reject
+               ))
+[GOOD] (assert uiFunRejector_model_56)
+Looking for solution 57
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and x!1 (not x!2)))))
+[GOOD] (define-fun q1_model57 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model57_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model57 x!0))))
+[GOOD] (define-fun q2_model57 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model57_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model57 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_57 () Bool 
+               (or q1_model57_reject
+                   q2_model57_reject
+               ))
+[GOOD] (assert uiFunRejector_model_57)
+Looking for solution 58
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) true)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 x!2) (and x!1 (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model58 ((x!0 Bool)) Bool
+          true
+       )
+[GOOD] (define-fun q1_model58_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model58 x!0))))
+[GOOD] (define-fun q2_model58 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model58_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model58 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_58 () Bool 
+               (or q1_model58_reject
+                   q2_model58_reject
+               ))
+[GOOD] (assert uiFunRejector_model_58)
+Looking for solution 59
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 x!2) (and x!1 (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) false))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) true))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model59 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model59_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model59 x!0))))
+[GOOD] (define-fun q2_model59 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 true) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model59_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model59 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_59 () Bool 
+               (or q1_model59_reject
+                   q2_model59_reject
+               ))
+[GOOD] (assert uiFunRejector_model_59)
+Looking for solution 60
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) (not x!1))))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) false)))
+[GOOD] (define-fun q1_model60 ((x!0 Bool)) Bool
+          (ite (and (= x!0 false)) true
+          false)
+       )
+[GOOD] (define-fun q1_model60_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model60 x!0))))
+[GOOD] (define-fun q2_model60 ((x!0 Bool) (x!1 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q2_model60_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model60 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_60 () Bool 
+               (or q1_model60_reject
+                   q2_model60_reject
+               ))
+[GOOD] (assert uiFunRejector_model_60)
+Looking for solution 61
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (and (not x!1) (not x!2)))))
+[GOOD] (define-fun q1_model61 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model61_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model61 x!0))))
+[GOOD] (define-fun q2_model61 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          false)
+       )
+[GOOD] (define-fun q2_model61_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model61 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_61 () Bool 
+               (or q1_model61_reject
+                   q2_model61_reject
+               ))
+[GOOD] (assert uiFunRejector_model_61)
+Looking for solution 62
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) x!1)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (or (and (not x!1) (not x!2)) (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model62 ((x!0 Bool)) Bool
+          (ite (and (= x!0 true)) true
+          false)
+       )
+[GOOD] (define-fun q1_model62_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model62 x!0))))
+[GOOD] (define-fun q2_model62 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model62_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model62 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_62 () Bool 
+               (or q1_model62_reject
+                   q2_model62_reject
+               ))
+[GOOD] (assert uiFunRejector_model_62)
+Looking for solution 63
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool))
+         (or (and (not x!1) (not x!2)) (and (not x!1) x!2)))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) true))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) false))
+[GOOD] (define-fun q1_model63 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model63_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model63 x!0))))
+[GOOD] (define-fun q2_model63 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 false) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model63_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model63 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_63 () Bool 
+               (or q1_model63_reject
+                   q2_model63_reject
+               ))
+[GOOD] (assert uiFunRejector_model_63)
+Looking for solution 64
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (q1))
+[RECV] ((q1 (lambda ((x!1 Bool)) false)))
+[SEND] (get-value (q2))
+[RECV] ((q2 (lambda ((x!1 Bool) (x!2 Bool)) (or (and x!1 x!2) (and (not x!1) (not x!2))))))
+[SEND] (get-value ((q2 false false)))
+[RECV] (((q2 false false) true))
+[SEND] (get-value ((q2 false true)))
+[RECV] (((q2 false true) false))
+[SEND] (get-value ((q2 true false)))
+[RECV] (((q2 true false) false))
+[SEND] (get-value ((q2 true true)))
+[RECV] (((q2 true true) true))
+[GOOD] (define-fun q1_model64 ((x!0 Bool)) Bool
+          false
+       )
+[GOOD] (define-fun q1_model64_reject () Bool
+          (exists ((x!0 Bool))
+                  (distinct (q1         x!0)
+                            (q1_model64 x!0))))
+[GOOD] (define-fun q2_model64 ((x!0 Bool) (x!1 Bool)) Bool
+          (ite (and (= x!0 false) (= x!1 false)) true
+          (ite (and (= x!0 true) (= x!1 true)) true
+          false))
+       )
+[GOOD] (define-fun q2_model64_reject () Bool
+          (exists ((x!0 Bool) (x!1 Bool))
+                  (distinct (q2         x!0 x!1)
+                            (q2_model64 x!0 x!1))))
+[GOOD] (define-fun uiFunRejector_model_64 () Bool 
+               (or q1_model64_reject
+                   q2_model64_reject
+               ))
+[GOOD] (assert uiFunRejector_model_64)
+Looking for solution 65
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+RESULT: Solution #1:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Solution #2:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Solution #3:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #4:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True 
+Solution #5:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True 
+Solution #6:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 _     _     = False
+Solution #7:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  True  = True 
+  q2 _     _     = False
+Solution #8:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True 
+Solution #9:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True 
+Solution #10:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #11:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #12:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #13:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #14:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True 
+Solution #15:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = False
+  q2 _     _    = True 
+Solution #16:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True 
+Solution #17:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True 
+Solution #18:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #19:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #20:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = True
+Solution #21:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True 
+Solution #22:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = False
+  q2 _    _    = True 
+Solution #23:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True 
+Solution #24:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Solution #25:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 _    _     = False
+Solution #26:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True 
+Solution #27:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 True True  = True 
+  q2 _    _     = False
+Solution #28:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 _     _    = False
+Solution #29:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True 
+  q2 _    _    = False
+Solution #30:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 _    _     = False
+Solution #31:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 _     _    = False
+Solution #32:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 True  True = True 
+  q2 _     _    = False
+Solution #33:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #34:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True 
+  q2 _    _    = False
+Solution #35:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 True True  = True 
+  q2 _    _     = False
+Solution #36:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 True  True = True 
+  q2 _     _    = False
+Solution #37:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 _     _    = False
+Solution #38:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True 
+Solution #39:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #40:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #41:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = False
+  q2 _     _     = True 
+Solution #42:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 _     _    = False
+Solution #43:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 True  True = True 
+  q2 _     _    = False
+Solution #44:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True = True 
+  q2 True  True = True 
+  q2 _     _    = False
+Solution #45:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True 
+Solution #46:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = False
+  q2 _    _     = True 
+Solution #47:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 False True  = True 
+  q2 _     _     = False
+Solution #48:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 _     _     = False
+Solution #49:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  True  = True 
+  q2 _     _     = False
+Solution #50:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  True  = True 
+  q2 _     _     = False
+Solution #51:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 _     _     = False
+Solution #52:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 False True  = True 
+  q2 _     _     = False
+Solution #53:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True 
+  q2 _    _    = False
+Solution #54:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False True  = True 
+  q2 True  False = True 
+  q2 _     _     = False
+Solution #55:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True True = True 
+  q2 _    _    = False
+Solution #56:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 _    _     = False
+Solution #57:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 _    _     = False
+Solution #58:
+  q1 :: Bool -> Bool
+  q1 _ = True
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 True True  = True 
+  q2 _    _     = False
+Solution #59:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 True False = True 
+  q2 True True  = True 
+  q2 _    _     = False
+Solution #60:
+  q1 :: Bool -> Bool
+  q1 False = True 
+  q1 _     = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 _ _ = False
+Solution #61:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 _     _     = False
+Solution #62:
+  q1 :: Bool -> Bool
+  q1 True = True 
+  q1 _    = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 False True  = True 
+  q2 _     _     = False
+Solution #63:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 False True  = True 
+  q2 _     _     = False
+Solution #64:
+  q1 :: Bool -> Bool
+  q1 _ = False
+
+  q2 :: Bool -> Bool -> Bool
+  q2 False False = True 
+  q2 True  True  = True 
+  q2 _     _     = False
+Found 64 different solutions.
diff --git a/SBVTestSuite/GoldFiles/unit.gold b/SBVTestSuite/GoldFiles/unit.gold
deleted file mode 100644
--- a/SBVTestSuite/GoldFiles/unit.gold
+++ /dev/null
@@ -1,29 +0,0 @@
-** Calling: z3 -nw -in -smt2
-[GOOD] ; Automatically generated by SBV. Do not edit.
-[GOOD] (set-option :print-success true)
-[GOOD] (set-option :global-declarations true)
-[GOOD] (set-option :smtlib2_compliant true)
-[GOOD] (set-option :diagnostic-output-channel "stdout")
-[GOOD] (set-option :produce-models true)
-[GOOD] (set-logic ALL) ; external query, using all logics.
-[GOOD] ; --- uninterpreted sorts ---
-[GOOD] ; --- tuples ---
-[GOOD] (declare-datatypes () ((tup-0 (tup-0))))
-[GOOD] ; --- literal constants ---
-[GOOD] (define-fun s_2 () Bool false)
-[GOOD] (define-fun s_1 () Bool true)
-[GOOD] ; --- skolem constants ---
-[GOOD] (declare-fun s0 () tup-0) ; tracks user variable "x"
-[GOOD] (declare-fun s1 () tup-0) ; tracks user variable "y"
-[GOOD] ; --- constant tables ---
-[GOOD] ; --- skolemized tables ---
-[GOOD] ; --- arrays ---
-[GOOD] ; --- uninterpreted constants ---
-[GOOD] ; --- user given axioms ---
-[GOOD] ; --- formula ---
-[GOOD] (define-fun s2 () Bool (= s0 s1))
-[GOOD] (assert s2)
-[SEND] (check-sat)
-[RECV] sat
-*** Solver   : Z3
-*** Exit code: ExitSuccess
diff --git a/SBVTestSuite/GoldFiles/validate_0.gold b/SBVTestSuite/GoldFiles/validate_0.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/validate_0.gold
@@ -0,0 +1,48 @@
+** Calling: abc -S "%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000"
+[ISSUE] ; Automatically generated by SBV. Do not edit.
+** Skipping heart-beat for the solver ABC
+** Backend solver ABC does not support global decls.
+** Some incremental calls, such as pop, will be limited.
+[ISSUE] (set-option :diagnostic-output-channel "stdout")
+[ISSUE] (set-option :produce-models true)
+[ISSUE] (set-logic QF_BV)
+[ISSUE] ; --- uninterpreted sorts ---
+[ISSUE] ; --- tuples ---
+[ISSUE] ; --- sums ---
+[ISSUE] ; --- literal constants ---
+[ISSUE] (define-fun s1 () (_ BitVec 8) #x0a)
+[ISSUE] ; --- skolem constants ---
+[ISSUE] (declare-fun s0 () (_ BitVec 8)) ; tracks user variable "x"
+[ISSUE] ; --- constant tables ---
+[ISSUE] ; --- skolemized tables ---
+[ISSUE] ; --- arrays ---
+[ISSUE] ; --- uninterpreted constants ---
+[ISSUE] ; --- user given axioms ---
+[ISSUE] ; --- formula ---
+[ISSUE] (define-fun s2 () Bool (bvult s0 s1))
+[ISSUE] (assert s2)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 #xff))
+*** Solver   : ABC
+*** Exit code: ExitSuccess
+[VALIDATE] Validating the model in the environment:
+[VALIDATE]       x = 255 :: Word8
+[VALIDATE] There are no constraints to check.
+[VALIDATE] Validating outputs.
+
+FINAL OUTPUT:
+*** Data.SBV: Model validation failure: Final output evaluated to False.
+*** 
+*** Environment:
+*** 
+***       x = 255 :: Word8
+*** 
+*** Backend solver returned a model that does not satisfy the constraints.
+*** This could indicate a bug in the backend solver, or SBV itself. Please report.
+***
+*** Alleged model:
+***
+*** Satisfiable. Model:
+***   x = 255 :: Word8
diff --git a/SBVTestSuite/GoldFiles/validate_1.gold b/SBVTestSuite/GoldFiles/validate_1.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/validate_1.gold
@@ -0,0 +1,51 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_FP)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () RoundingMode roundTowardZero)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ FloatingPoint  8 24)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (fp.add s1 s0 s0))
+[GOOD] (define-fun s3 () Bool (fp.eq s0 s2))
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (_ +zero 8 24)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[VALIDATE] Validating the model in the environment:
+[VALIDATE]       x = 0.0 :: Float
+[VALIDATE] There are no constraints to check.
+[VALIDATE] Validating outputs.
+
+FINAL OUTPUT:
+*** Data.SBV: Cannot validate the model, since s4 is not concretely computable.
+*** 
+*** Environment:
+*** 
+***       x = 0.0 :: Float
+*** 
+*** Not all floating point operations are supported concretely.
+*** 
+*** SBV's model validator is incomplete, and cannot handle this particular case.
+*** Please report this as a feature request or possibly a bug!
+***
+*** Alleged model:
+***
+*** Satisfiable. Model:
+***   x = 0.0 :: Float
diff --git a/SBVTestSuite/GoldFiles/validate_2.gold b/SBVTestSuite/GoldFiles/validate_2.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/validate_2.gold
@@ -0,0 +1,51 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic QF_FP)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s1 () RoundingMode roundNearestTiesToEven)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ FloatingPoint  8 24)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () (_ FloatingPoint  8 24) (fp.fma s1 s0 s0 s0))
+[GOOD] (define-fun s3 () Bool (fp.eq s0 s2))
+[GOOD] (assert s3)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (fp #b0 #x40 #b00000001000000000010000)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[VALIDATE] Validating the model in the environment:
+[VALIDATE]       x = 1.0884394e-19 :: Float
+[VALIDATE] There are no constraints to check.
+[VALIDATE] Validating outputs.
+
+FINAL OUTPUT:
+*** Data.SBV: Cannot validate the model, since s4 is not concretely computable.
+*** 
+*** Environment:
+*** 
+***       x = 1.0884394e-19 :: Float
+*** 
+*** Floating point FMA operation is not supported concretely.
+*** 
+*** SBV's model validator is incomplete, and cannot handle this particular case.
+*** Please report this as a feature request or possibly a bug!
+***
+*** Alleged model:
+***
+*** Satisfiable. Model:
+***   x = 1.0884394e-19 :: Float
diff --git a/SBVTestSuite/GoldFiles/validate_3.gold b/SBVTestSuite/GoldFiles/validate_3.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/validate_3.gold
@@ -0,0 +1,28 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Unsatisfiable
diff --git a/SBVTestSuite/GoldFiles/validate_4.gold b/SBVTestSuite/GoldFiles/validate_4.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/validate_4.gold
@@ -0,0 +1,29 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (assert false)
+[GOOD] (assert false)
+[SEND] (check-sat)
+[RECV] unsat
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+
+FINAL OUTPUT:
+Q.E.D.
diff --git a/SBVTestSuite/GoldFiles/validate_5.gold b/SBVTestSuite/GoldFiles/validate_5.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/validate_5.gold
@@ -0,0 +1,50 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 12)
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "y"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Bool (> s0 s1))
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s6 () Int (+ s1 s5))
+[GOOD] (define-fun s7 () Bool (= s0 s6))
+[GOOD] (assert s2)
+[GOOD] (assert s4)
+[GOOD] (assert s7)
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 10))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[VALIDATE] Validating the model in the environment:
+[VALIDATE]       x = 13 :: Integer
+[VALIDATE]       y = 10 :: Integer
+[VALIDATE] Validating 2 constraint(s).
+[VALIDATE] Validated all constraints.
+[VALIDATE] Validating outputs.
+[VALIDATE] All outputs are satisfied. Validation complete.
+
+FINAL OUTPUT:
+Satisfiable. Model:
+  x = 13 :: Integer
+  y = 10 :: Integer
diff --git a/SBVTestSuite/GoldFiles/validate_6.gold b/SBVTestSuite/GoldFiles/validate_6.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/validate_6.gold
@@ -0,0 +1,50 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL) ; has unbounded values, using catch-all.
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] (define-fun s3 () Int 12)
+[GOOD] (define-fun s5 () Int 3)
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () Int) ; tracks user variable "x"
+[GOOD] (declare-fun s1 () Int) ; tracks user variable "y"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (define-fun s2 () Bool (> s0 s1))
+[GOOD] (define-fun s4 () Bool (> s0 s3))
+[GOOD] (define-fun s6 () Int (+ s1 s5))
+[GOOD] (define-fun s7 () Bool (= s0 s6))
+[GOOD] (assert s2)
+[GOOD] (assert s4)
+[GOOD] (assert (not s7))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 13))
+[SEND] (get-value (s1))
+[RECV] ((s1 11))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[VALIDATE] Validating the model in the environment:
+[VALIDATE]       x = 13 :: Integer
+[VALIDATE]       y = 11 :: Integer
+[VALIDATE] Validating 2 constraint(s).
+[VALIDATE] Validated all constraints.
+[VALIDATE] Validating outputs.
+[VALIDATE] Counterexample is validated.
+
+FINAL OUTPUT:
+Falsifiable. Counter-example:
+  x = 13 :: Integer
+  y = 11 :: Integer
diff --git a/SBVTestSuite/GoldFiles/validate_7.gold b/SBVTestSuite/GoldFiles/validate_7.gold
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/GoldFiles/validate_7.gold
@@ -0,0 +1,46 @@
+** Calling: z3 -nw -in -smt2
+[GOOD] ; Automatically generated by SBV. Do not edit.
+[GOOD] (set-option :print-success true)
+[GOOD] (set-option :global-declarations true)
+[GOOD] (set-option :smtlib2_compliant true)
+[GOOD] (set-option :diagnostic-output-channel "stdout")
+[GOOD] (set-option :produce-models true)
+[GOOD] (set-logic ALL)
+[GOOD] ; --- uninterpreted sorts ---
+[GOOD] ; --- tuples ---
+[GOOD] ; --- sums ---
+[GOOD] ; --- literal constants ---
+[GOOD] ; --- skolem constants ---
+[GOOD] (declare-fun s0 () (_ FloatingPoint  8 24)) ; tracks user variable "x"
+[GOOD] ; --- constant tables ---
+[GOOD] ; --- skolemized tables ---
+[GOOD] ; --- arrays ---
+[GOOD] ; --- uninterpreted constants ---
+[GOOD] ; --- user given axioms ---
+[GOOD] ; --- formula ---
+[GOOD] (assert (forall ((s1 (_ FloatingPoint  8 24)))
+                   (let ((s2 (fp.isNaN s1)))
+                   (let ((s3 (fp.isInfinite s1)))
+                   (let ((s4 (or s2 s3)))
+                   (let ((s5 (not s4)))
+                   (let ((s6 (not s5)))
+                   (let ((s7 (fp.leq s0 s1)))
+                   (let ((s8 (or s6 s7)))
+                   s8)))))))))
+[SEND] (check-sat)
+[RECV] sat
+[SEND] (get-value (s0))
+[RECV] ((s0 (_ -oo 8 24)))
+*** Solver   : Z3
+*** Exit code: ExitSuccess
+[VALIDATE] Validating the model in the environment:
+[VALIDATE]       x =                -Infinity :: Float
+[VALIDATE]       y = <universally quantified> :: Float
+
+EXCEPTION RAISED:
+*** Data.SBV: Cannot validate models in the presence of universally quantified variable "y"
+***
+***   To turn validation off, use `cfg{validateModel = False}`
+***
+*** Validation engine is not capable of handling this case. Failed to validate.
+
diff --git a/SBVTestSuite/SBVDocTest.hs b/SBVTestSuite/SBVDocTest.hs
--- a/SBVTestSuite/SBVDocTest.hs
+++ b/SBVTestSuite/SBVDocTest.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : SBVDocTest
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -41,7 +41,7 @@
                                              docFiles <- glob "Documentation/SBV/**/*.hs"
 
                                              let allFiles  = srcFiles ++ docFiles
-                                                 testFiles = filter (\nm -> not (skipWindows nm || skipRemote nm)) allFiles
+                                                 testFiles = filter (\nm -> not (skipWindows nm || skipRemote nm || skipLocal nm)) allFiles
 
                                                  args = ["--fast", "--no-magic"]
 
@@ -60,10 +60,15 @@
                skipRemote nm
                  | not onRemote = False
                  | True         = noGood nm skipList
-                 where skipList = [ "Interpolants.hs"  -- The following test requires mathSAT, so can't run on remote
+                 where skipList = [ "Interpolants.hs"  -- This test requires mathSAT, so can't run on remote
                                   , "HexPuzzle.hs"     -- Doctest is way too slow on this with ghci loading, sigh
-                                  , "MultMask.hs"      -- Also, quite slow
                                   ]
+
+               -- These are the doctests we currently skip *everywhere* because there's some issue
+               -- with an external tool or some other issue that stops us from fixing it. NB. Each
+               -- of these should be accompanied by a ticket!
+               skipLocal nm = noGood nm skipList
+                 where skipList = []
 
 -- Pick (about) the given percentage of files
 pickPercentage :: Int -> [String] -> IO [String]
diff --git a/SBVTestSuite/SBVHLint.hs b/SBVTestSuite/SBVHLint.hs
--- a/SBVTestSuite/SBVHLint.hs
+++ b/SBVTestSuite/SBVHLint.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : SBVHLint
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/SBVTest.hs b/SBVTestSuite/SBVTest.hs
--- a/SBVTestSuite/SBVTest.hs
+++ b/SBVTestSuite/SBVTest.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : SBVTest
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -27,23 +27,29 @@
 import qualified TestSuite.Basics.ArithSolver
 import qualified TestSuite.Basics.Assert
 import qualified TestSuite.Basics.BasicTests
+import qualified TestSuite.Basics.BarrelRotate
 import qualified TestSuite.Basics.BoundedList
+import qualified TestSuite.Basics.DynSign
 import qualified TestSuite.Basics.Exceptions
 import qualified TestSuite.Basics.GenBenchmark
 import qualified TestSuite.Basics.Higher
 import qualified TestSuite.Basics.Index
 import qualified TestSuite.Basics.IteTest
 import qualified TestSuite.Basics.List
+import qualified TestSuite.Basics.ModelValidate
 import qualified TestSuite.Basics.ProofTests
 import qualified TestSuite.Basics.PseudoBoolean
 import qualified TestSuite.Basics.QRem
 import qualified TestSuite.Basics.Quantifiers
 import qualified TestSuite.Basics.Recursive
+import qualified TestSuite.Basics.Set
 import qualified TestSuite.Basics.SmallShifts
 import qualified TestSuite.Basics.SquashReals
 import qualified TestSuite.Basics.String
+import qualified TestSuite.Basics.Sum
 import qualified TestSuite.Basics.TOut
 import qualified TestSuite.Basics.Tuple
+import qualified TestSuite.Basics.UISat
 import qualified TestSuite.BitPrecise.BitTricks
 import qualified TestSuite.BitPrecise.Legato
 import qualified TestSuite.BitPrecise.MergeSort
@@ -69,9 +75,11 @@
 import qualified TestSuite.Optimization.Basics
 import qualified TestSuite.Optimization.Combined
 import qualified TestSuite.Optimization.ExtensionField
+import qualified TestSuite.Optimization.Floats
+import qualified TestSuite.Optimization.NoOpt
 import qualified TestSuite.Optimization.Quantified
 import qualified TestSuite.Optimization.Reals
-import qualified TestSuite.Optimization.NoOpt
+import qualified TestSuite.Optimization.Tuples
 import qualified TestSuite.Overflows.Arithmetic
 import qualified TestSuite.Overflows.Casts
 import qualified TestSuite.Polynomials.Polynomials
@@ -98,7 +106,10 @@
 import qualified TestSuite.Queries.Interpolants
 import qualified TestSuite.Queries.Lists
 import qualified TestSuite.Queries.Strings
+import qualified TestSuite.Queries.Sums
 import qualified TestSuite.Queries.Tuples
+import qualified TestSuite.Queries.UISat
+import qualified TestSuite.Queries.UISatEx
 import qualified TestSuite.Queries.Uninterpreted
 import qualified TestSuite.QuickCheck.QC
 import qualified TestSuite.Transformers.SymbolicEval
@@ -141,6 +152,8 @@
 localOnlyTests :: TestTree
 localOnlyTests = testGroup "SBVLocalOnlyTests" [
                      TestSuite.Basics.Exceptions.testsLocal
+                   , TestSuite.Basics.BarrelRotate.tests      -- Requires CVC4
+                   , TestSuite.Basics.ModelValidate.testsABC  -- Requires ABC
                    , TestSuite.Queries.BasicQuery.tests
                    , TestSuite.Queries.BadOption.tests
                    , TestSuite.Queries.Int_ABC.tests
@@ -148,10 +161,8 @@
                    , TestSuite.Queries.Int_CVC4.tests
                    , TestSuite.Queries.Int_Mathsat.tests
                    , TestSuite.Queries.Int_Yices.tests
-                   -- quick-check tests take a long time, so just run them locally:
-                   , TestSuite.QuickCheck.QC.tests
-                   -- interpolant tests require MathSAT, run locally:
-                   , TestSuite.Queries.Interpolants.tests
+                   , TestSuite.Queries.Interpolants.tests     -- requires MathSat
+                   , TestSuite.QuickCheck.QC.tests            -- runs too slow, so only local
                    ]
 
 -- | Remaining tests
@@ -165,22 +176,27 @@
                , TestSuite.Basics.Assert.tests
                , TestSuite.Basics.BasicTests.tests
                , TestSuite.Basics.BoundedList.tests
+               , TestSuite.Basics.DynSign.tests
                , TestSuite.Basics.Exceptions.testsRemote
                , TestSuite.Basics.GenBenchmark.tests
                , TestSuite.Basics.Higher.tests
                , TestSuite.Basics.Index.tests
                , TestSuite.Basics.IteTest.tests
                , TestSuite.Basics.List.tests
+               , TestSuite.Basics.ModelValidate.tests
                , TestSuite.Basics.ProofTests.tests
                , TestSuite.Basics.PseudoBoolean.tests
                , TestSuite.Basics.QRem.tests
                , TestSuite.Basics.Quantifiers.tests
                , TestSuite.Basics.Recursive.tests
+               , TestSuite.Basics.Set.tests
                , TestSuite.Basics.SmallShifts.tests
                , TestSuite.Basics.SquashReals.tests
                , TestSuite.Basics.String.tests
+               , TestSuite.Basics.Sum.tests
                , TestSuite.Basics.TOut.tests
                , TestSuite.Basics.Tuple.tests
+               , TestSuite.Basics.UISat.tests
                , TestSuite.BitPrecise.BitTricks.tests
                , TestSuite.BitPrecise.Legato.tests
                , TestSuite.BitPrecise.MergeSort.tests
@@ -206,9 +222,11 @@
                , TestSuite.Optimization.Basics.tests
                , TestSuite.Optimization.Combined.tests
                , TestSuite.Optimization.ExtensionField.tests
+               , TestSuite.Optimization.Floats.tests
+               , TestSuite.Optimization.NoOpt.tests
+               , TestSuite.Optimization.Tuples.tests
                , TestSuite.Optimization.Quantified.tests
                , TestSuite.Optimization.Reals.tests
-               , TestSuite.Optimization.NoOpt.tests
                , TestSuite.Overflows.Arithmetic.tests
                , TestSuite.Overflows.Casts.tests
                , TestSuite.Polynomials.Polynomials.tests
@@ -227,7 +245,10 @@
                , TestSuite.Queries.Int_Z3.tests
                , TestSuite.Queries.Lists.tests
                , TestSuite.Queries.Strings.tests
+               , TestSuite.Queries.Sums.tests
                , TestSuite.Queries.Tuples.tests
+               , TestSuite.Queries.UISat.tests
+               , TestSuite.Queries.UISatEx.tests
                , TestSuite.Queries.Uninterpreted.tests
                , TestSuite.Transformers.SymbolicEval.tests
                , TestSuite.Uninterpreted.AUF.tests
diff --git a/SBVTestSuite/TestSuite/Arrays/InitVals.hs b/SBVTestSuite/TestSuite/Arrays/InitVals.hs
--- a/SBVTestSuite/TestSuite/Arrays/InitVals.hs
+++ b/SBVTestSuite/TestSuite/Arrays/InitVals.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Arrays.InitVals
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Arrays/Memory.hs b/SBVTestSuite/TestSuite/Arrays/Memory.hs
--- a/SBVTestSuite/TestSuite/Arrays/Memory.hs
+++ b/SBVTestSuite/TestSuite/Arrays/Memory.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Arrays.Memory
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Arrays/Query.hs b/SBVTestSuite/TestSuite/Arrays/Query.hs
--- a/SBVTestSuite/TestSuite/Arrays/Query.hs
+++ b/SBVTestSuite/TestSuite/Arrays/Query.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Arrays.Query
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/AllSat.hs b/SBVTestSuite/TestSuite/Basics/AllSat.hs
--- a/SBVTestSuite/TestSuite/Basics/AllSat.hs
+++ b/SBVTestSuite/TestSuite/Basics/AllSat.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.AllSat
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -31,7 +31,7 @@
     ]
 
 srt :: AllSatResult -> AllSatResult
-srt (AllSatResult (b1, b2, rs)) = AllSatResult (b1, b2, sortOn getModelDictionary rs)
+srt (AllSatResult (b1, b2, b3, rs)) = AllSatResult (b1, b2, b3, sortOn getModelDictionary rs)
 
 newtype Q = Q () deriving (Eq, Ord, Data, Read, Show, SymVal, HasKind)
 type SQ = SBV Q
diff --git a/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs b/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs
--- a/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs
+++ b/SBVTestSuite/TestSuite/Basics/ArithNoSolver.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.ArithNoSolver
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -157,23 +157,23 @@
 -- A few tests for mixed-size shifts
 genShiftMixSize :: [TestTree]
 genShiftMixSize = map mkTest $
-           map pair [(show x, show y, "shl_w8_w16", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- w8s,  y <- yw16s]
-        ++ map pair [(show x, show y, "shr_w8_w16", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- w8s,  y <- yw16s]
-        ++ map pair [(show x, show y, "shl_w16_w8", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- w16s, y <- w8s]
-        ++ map pair [(show x, show y, "shr_w16_w8", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- w16s, y <- w8s]
-        ++ map pair [(show x, show y, "shl_i8_i16", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- i8s,  y <- yi16s]
-        ++ map pair [(show x, show y, "shr_i8_i16", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- i8s,  y <- yi16s]
-        ++ map pair [(show x, show y, "shl_i16_i8", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- i16s, y <- i8s, y >= 0]
-        ++ map pair [(show x, show y, "shr_i16_i8", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- i16s, y <- i8s, y >= 0]
-        ++ map pair [(show x, show y, "shl_w8_i16", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- w8s,  y <- yi16s]
-        ++ map pair [(show x, show y, "shr_w8_i16", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- w8s,  y <- yi16s]
-        ++ map pair [(show x, show y, "shl_w16_i8", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- w16s, y <- i8s, y >= 0]
-        ++ map pair [(show x, show y, "shr_w16_i8", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- w16s, y <- i8s, y >= 0]
-        ++ map pair [(show x, show y, "shl_i8_w16", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- i8s,  y <- yw16s]
-        ++ map pair [(show x, show y, "shr_i8_w16", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- i8s,  y <- yw16s]
-        ++ map pair [(show x, show y, "shl_i16_w8", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- i16s, y <- w8s]
-        ++ map pair [(show x, show y, "shr_i16_w8", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- i16s, y <- w8s]
-   where pair :: (SymVal a, Show a) => (String, String, String, SBV a, a) -> (String, Bool)
+           [pair (show x, show y, "shl_w8_w16", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- w8s,  y <- yw16s]
+        ++ [pair (show x, show y, "shr_w8_w16", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- w8s,  y <- yw16s]
+        ++ [pair (show x, show y, "shl_w16_w8", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- w16s, y <- w8s]
+        ++ [pair (show x, show y, "shr_w16_w8", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- w16s, y <- w8s]
+        ++ [pair (show x, show y, "shl_i8_i16", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- i8s,  y <- yi16s]
+        ++ [pair (show x, show y, "shr_i8_i16", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- i8s,  y <- yi16s]
+        ++ [pair (show x, show y, "shl_i16_i8", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- i16s, y <- i8s, y >= 0]
+        ++ [pair (show x, show y, "shr_i16_i8", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- i16s, y <- i8s, y >= 0]
+        ++ [pair (show x, show y, "shl_w8_i16", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- w8s,  y <- yi16s]
+        ++ [pair (show x, show y, "shr_w8_i16", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- w8s,  y <- yi16s]
+        ++ [pair (show x, show y, "shl_w16_i8", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- w16s, y <- i8s, y >= 0]
+        ++ [pair (show x, show y, "shr_w16_i8", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- w16s, y <- i8s, y >= 0]
+        ++ [pair (show x, show y, "shl_i8_w16", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- i8s,  y <- yw16s]
+        ++ [pair (show x, show y, "shr_i8_w16", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- i8s,  y <- yw16s]
+        ++ [pair (show x, show y, "shl_i16_w8", literal x `sShiftLeft`  literal y,  x `shiftL` fromIntegral y) | x <- i16s, y <- w8s]
+        ++ [pair (show x, show y, "shr_i16_w8", literal x `sShiftRight` literal y,  x `shiftR` fromIntegral y) | x <- i16s, y <- w8s]
+   where pair :: (Eq a, SymVal a, Show a) => (String, String, String, SBV a, a) -> (String, Bool)
          pair (x, y, l, sr, lr) = (l ++ "." ++ x ++ "_" ++ y ++ "_" ++  show (unliteral sr) ++ "_" ++ show lr, isJust (unliteral sr) && unliteral sr == Just lr)
          mkTest (l, s) = testCase ("arithCF-genShiftMixSize" ++ l) (s `showsAs` "True")
 
@@ -367,74 +367,50 @@
                                ++ floatRun2   "fpIsEqualObject" fpIsEqualObjectH fpIsEqualObject combE
                                ++ doubleRun2  "fpIsEqualObject" fpIsEqualObjectH fpIsEqualObject combE
 
-        converts =  map cvtTest  [("toFP_Int8_ToFloat",     show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- i8s ]
-                 ++ map cvtTest  [("toFP_Int16_ToFloat",    show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- i16s]
-                 ++ map cvtTest  [("toFP_Int32_ToFloat",    show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- i32s]
-                 ++ map cvtTest  [("toFP_Int64_ToFloat",    show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- i64s]
-                 ++ map cvtTest  [("toFP_Word8_ToFloat",    show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- w8s ]
-                 ++ map cvtTest  [("toFP_Word16_ToFloat",   show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- w16s]
-                 ++ map cvtTest  [("toFP_Word32_ToFloat",   show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- w32s]
-                 ++ map cvtTest  [("toFP_Word64_ToFloat",   show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- w64s]
-                 ++ map cvtTest  [("toFP_Float_ToFloat",    show x, toSFloat  sRNE (literal x),                  literal x ) | x <- fs  ]
-                 ++ map cvtTest  [("toFP_Double_ToFloat",   show x, toSFloat  sRNE (literal x),           literal (fp2fp x)) | x <- ds  ]
-                 ++ map cvtTest  [("toFP_Integer_ToFloat",  show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- iUBs]
-                 ++ map cvtTest  [("toFP_Real_ToFloat",     show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- rs  ]
-
-                 ++ map cvtTest  [("toFP_Int8_ToDouble",    show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- i8s ]
-                 ++ map cvtTest  [("toFP_Int16_ToDouble",   show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- i16s]
-                 ++ map cvtTest  [("toFP_Int32_ToDouble",   show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- i32s]
-                 ++ map cvtTest  [("toFP_Int64_ToDouble",   show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- i64s]
-                 ++ map cvtTest  [("toFP_Word8_ToDouble",   show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- w8s ]
-                 ++ map cvtTest  [("toFP_Word16_ToDouble",  show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- w16s]
-                 ++ map cvtTest  [("toFP_Word32_ToDouble",  show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- w32s]
-                 ++ map cvtTest  [("toFP_Word64_ToDouble",  show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- w64s]
-                 ++ map cvtTest  [("toFP_Float_ToDouble",   show x, toSDouble sRNE (literal x),           literal (fp2fp x)) | x <- fs  ]
-                 ++ map cvtTest  [("toFP_Double_ToDouble",  show x, toSDouble sRNE (literal x),                   literal x) | x <- ds  ]
-                 ++ map cvtTest  [("toFP_Integer_ToDouble", show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- iUBs]
-                 ++ map cvtTest  [("toFP_Real_ToDouble",    show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- rs  ]
-
-                 ++ map cvtTestI [("fromFP_Float_ToInt8",    show x, (fromSFloat sRNE :: SFloat -> SInt8)    (literal x), ((fromIntegral :: Integer -> SInt8)    . fpRound0) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToInt16",   show x, (fromSFloat sRNE :: SFloat -> SInt16)   (literal x), ((fromIntegral :: Integer -> SInt16)   . fpRound0) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToInt32",   show x, (fromSFloat sRNE :: SFloat -> SInt32)   (literal x), ((fromIntegral :: Integer -> SInt32)   . fpRound0) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToInt64",   show x, (fromSFloat sRNE :: SFloat -> SInt64)   (literal x), ((fromIntegral :: Integer -> SInt64)   . fpRound0) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToWord8",   show x, (fromSFloat sRNE :: SFloat -> SWord8)   (literal x), ((fromIntegral :: Integer -> SWord8)   . fpRound0) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToWord16",  show x, (fromSFloat sRNE :: SFloat -> SWord16)  (literal x), ((fromIntegral :: Integer -> SWord16)  . fpRound0) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToWord32",  show x, (fromSFloat sRNE :: SFloat -> SWord32)  (literal x), ((fromIntegral :: Integer -> SWord32)  . fpRound0) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToWord64",  show x, (fromSFloat sRNE :: SFloat -> SWord64)  (literal x), ((fromIntegral :: Integer -> SWord64)  . fpRound0) x) | x <- fs]
-                 ++ map cvtTest  [("fromFP_Float_ToFloat",   show x, (fromSFloat sRNE :: SFloat -> SFloat)   (literal x),                                            literal x) | x <- fs]
-                 ++ map cvtTest  [("fromFP_Float_ToDouble",  show x, (fromSFloat sRNE :: SFloat -> SDouble)  (literal x),                                 (literal .  fp2fp) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToInteger", show x, (fromSFloat sRNE :: SFloat -> SInteger) (literal x), ((fromIntegral :: Integer -> SInteger) . fpRound0) x) | x <- fs]
-                 ++ map cvtTestI [("fromFP_Float_ToReal",    show x, (fromSFloat sRNE :: SFloat -> SReal)    (literal x),                          (fromRational . fpRatio0) x) | x <- fs]
+        converts =   [cvtTest ("toFP_Int8_ToFloat",     show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- i8s ]
+                 ++  [cvtTest ("toFP_Int16_ToFloat",    show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- i16s]
+                 ++  [cvtTest ("toFP_Int32_ToFloat",    show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- i32s]
+                 ++  [cvtTest ("toFP_Int64_ToFloat",    show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- i64s]
+                 ++  [cvtTest ("toFP_Word8_ToFloat",    show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- w8s ]
+                 ++  [cvtTest ("toFP_Word16_ToFloat",   show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- w16s]
+                 ++  [cvtTest ("toFP_Word32_ToFloat",   show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- w32s]
+                 ++  [cvtTest ("toFP_Word64_ToFloat",   show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- w64s]
+                 ++  [cvtTest ("toFP_Float_ToFloat",    show x, toSFloat  sRNE (literal x),                  literal x ) | x <- fs  ]
+                 ++  [cvtTest ("toFP_Double_ToFloat",   show x, toSFloat  sRNE (literal x),           literal (fp2fp x)) | x <- ds  ]
+                 ++  [cvtTest ("toFP_Integer_ToFloat",  show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- iUBs]
+                 ++  [cvtTest ("toFP_Real_ToFloat",     show x, toSFloat  sRNE (literal x), fromRational (toRational x)) | x <- rs  ]
 
-                 ++ map cvtTestI [("fromFP_Double_ToInt8",    show x, (fromSDouble sRNE :: SDouble -> SInt8)    (literal x), ((fromIntegral :: Integer -> SInt8)    . fpRound0) x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToInt16",   show x, (fromSDouble sRNE :: SDouble -> SInt16)   (literal x), ((fromIntegral :: Integer -> SInt16)   . fpRound0) x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToInt32",   show x, (fromSDouble sRNE :: SDouble -> SInt32)   (literal x), ((fromIntegral :: Integer -> SInt32)   . fpRound0) x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToInt64",   show x, (fromSDouble sRNE :: SDouble -> SInt64)   (literal x), ((fromIntegral :: Integer -> SInt64)   . fpRound0) x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToWord8",   show x, (fromSDouble sRNE :: SDouble -> SWord8)   (literal x), ((fromIntegral :: Integer -> SWord8)   . fpRound0) x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToWord16",  show x, (fromSDouble sRNE :: SDouble -> SWord16)  (literal x), ((fromIntegral :: Integer -> SWord16)  . fpRound0) x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToWord32",  show x, (fromSDouble sRNE :: SDouble -> SWord32)  (literal x), ((fromIntegral :: Integer -> SWord32)  . fpRound0) x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToWord64",  show x, (fromSDouble sRNE :: SDouble -> SWord64)  (literal x), ((fromIntegral :: Integer -> SWord64)  . fpRound0) x) | x <- ds]
-                 ++ map cvtTest  [("fromFP_Double_ToFloat",   show x, (fromSDouble sRNE :: SDouble -> SFloat)   (literal x),                                (literal  .  fp2fp) x) | x <- ds]
-                 ++ map cvtTest  [("fromFP_Double_ToDouble",  show x, (fromSDouble sRNE :: SDouble -> SDouble)  (literal x),                                            literal x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToInteger", show x, (fromSDouble sRNE :: SDouble -> SInteger) (literal x), ((fromIntegral :: Integer -> SInteger) . fpRound0) x) | x <- ds]
-                 ++ map cvtTestI [("fromFP_Double_ToReal",    show x, (fromSDouble sRNE :: SDouble -> SReal)    (literal x),                          (fromRational . fpRatio0) x) | x <- ds]
+                 ++  [cvtTest ("toFP_Int8_ToDouble",    show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- i8s ]
+                 ++  [cvtTest ("toFP_Int16_ToDouble",   show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- i16s]
+                 ++  [cvtTest ("toFP_Int32_ToDouble",   show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- i32s]
+                 ++  [cvtTest ("toFP_Int64_ToDouble",   show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- i64s]
+                 ++  [cvtTest ("toFP_Word8_ToDouble",   show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- w8s ]
+                 ++  [cvtTest ("toFP_Word16_ToDouble",  show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- w16s]
+                 ++  [cvtTest ("toFP_Word32_ToDouble",  show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- w32s]
+                 ++  [cvtTest ("toFP_Word64_ToDouble",  show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- w64s]
+                 ++  [cvtTest ("toFP_Float_ToDouble",   show x, toSDouble sRNE (literal x),           literal (fp2fp x)) | x <- fs  ]
+                 ++  [cvtTest ("toFP_Double_ToDouble",  show x, toSDouble sRNE (literal x),                   literal x) | x <- ds  ]
+                 ++  [cvtTest ("toFP_Integer_ToDouble", show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- iUBs]
+                 ++  [cvtTest ("toFP_Real_ToDouble",    show x, toSDouble sRNE (literal x), fromRational (toRational x)) | x <- rs  ]
 
-                 ++ map cvtTest  [("reinterp_Word32_Float",  show x, sWord32AsSFloat  (literal x), literal (CN.wordToFloat  x)) | x <- w32s]
-                 ++ map cvtTest  [("reinterp_Word64_Double", show x, sWord64AsSDouble (literal x), literal (CN.wordToDouble x)) | x <- w64s]
+                 -- NB. We don't constant fold float/double conversions, so we skip these
+                 --
+                 ++  [cvtTest  ("reinterp_Word32_Float",  show x, sWord32AsSFloat  (literal x), literal (CN.wordToFloat  x)) | x <- w32s]
+                 ++  [cvtTest  ("reinterp_Word64_Double", show x, sWord64AsSDouble (literal x), literal (CN.wordToDouble x)) | x <- w64s]
 
-                 ++ map cvtTestI [("reinterp_Float_Word32",  show x, sFloatAsSWord32  (literal x), literal (CN.floatToWord x))  | x <- fs, not (isNaN x)] -- Not unique for NaN
-                 ++ map cvtTestI [("reinterp_Double_Word64", show x, sDoubleAsSWord64 (literal x), literal (CN.doubleToWord x)) | x <- ds, not (isNaN x)] -- Not unique for NaN
+                 ++  [cvtTestI ("reinterp_Float_Word32",  show x, sFloatAsSWord32  (literal x), CN.floatToWord x)  | x <- fs, not (isNaN x)] -- Not unique for NaN
+                 ++  [cvtTestI ("reinterp_Double_Word64", show x, sDoubleAsSWord64 (literal x), CN.doubleToWord x) | x <- ds, not (isNaN x)] -- Not unique for NaN
 
-        floatRun1   nm f g cmb = map (nm,) [cmb (x,    f x,   extract (g                         (literal x)))             | x <- fs]
-        doubleRun1  nm f g cmb = map (nm,) [cmb (x,    f x,   extract (g                         (literal x)))             | x <- ds]
-        floatRun1M  nm f g cmb = map (nm,) [cmb (x,    f x,   extract (g sRNE (literal x)))                                | x <- fs]
-        doubleRun1M nm f g cmb = map (nm,) [cmb (x,    f x,   extract (g sRNE (literal x)))                                | x <- ds]
-        floatRun2   nm f g cmb = map (nm,) [cmb (x, y, f x y, extract (g                         (literal x) (literal y))) | x <- fs, y <- fs]
-        doubleRun2  nm f g cmb = map (nm,) [cmb (x, y, f x y, extract (g                         (literal x) (literal y))) | x <- ds, y <- ds]
-        floatRun2M  nm f g cmb = map (nm,) [cmb (x, y, f x y, extract (g sRNE (literal x) (literal y))) | x <- fs, y <- fs]
-        doubleRun2M nm f g cmb = map (nm,) [cmb (x, y, f x y, extract (g sRNE (literal x) (literal y))) | x <- ds, y <- ds]
-        floatRunMM  nm f g cmb = map (nm,) [cmb (x, y, f x y, extract (g                         (literal x) (literal y))) | x <- fs, y <- fs, not (alt0 x y || alt0 y x)]
-        doubleRunMM nm f g cmb = map (nm,) [cmb (x, y, f x y, extract (g                         (literal x) (literal y))) | x <- ds, y <- ds, not (alt0 x y || alt0 y x)]
+        floatRun1   nm f g cmb = [(nm, cmb (x,    f x,   extract (g                     (literal x))))             | x <- fs]
+        doubleRun1  nm f g cmb = [(nm, cmb (x,    f x,   extract (g                     (literal x))))             | x <- ds]
+        floatRun1M  nm f g cmb = [(nm, cmb (x,    f x,   extract (g sRNE (literal x))))                            | x <- fs]
+        doubleRun1M nm f g cmb = [(nm, cmb (x,    f x,   extract (g sRNE (literal x))))                            | x <- ds]
+        floatRun2   nm f g cmb = [(nm, cmb (x, y, f x y, extract (g                     (literal x) (literal y)))) | x <- fs, y <- fs]
+        doubleRun2  nm f g cmb = [(nm, cmb (x, y, f x y, extract (g                     (literal x) (literal y)))) | x <- ds, y <- ds]
+        floatRun2M  nm f g cmb = [(nm, cmb (x, y, f x y, extract (g sRNE (literal x)    (literal y))))             | x <- fs, y <- fs]
+        doubleRun2M nm f g cmb = [(nm, cmb (x, y, f x y, extract (g sRNE (literal x)    (literal y))))             | x <- ds, y <- ds]
+        floatRunMM  nm f g cmb = [(nm, cmb (x, y, f x y, extract (g                     (literal x) (literal y)))) | x <- fs, y <- fs, not (alt0 x y || alt0 y x)]
+        doubleRunMM nm f g cmb = [(nm, cmb (x, y, f x y, extract (g                     (literal x) (literal y)))) | x <- ds, y <- ds, not (alt0 x y || alt0 y x)]
         -- fpMin/fpMax: skip +0/-0 case as this is underspecified
         alt0 x y = isNegativeZero x && y == 0 && not (isNegativeZero y)
         uTests = map mkTest1 $  concatMap (checkPred fs sfs) predicates
@@ -452,8 +428,8 @@
           | isNaN x || isNaN y = f a b
           | True               = a == b
 
-        cvtTest  (nm, x, a, b)  = testCase ("arithCF-" ++ nm ++ "." ++ x) (same (extract a) (extract b) `showsAs` "True")
-        cvtTestI (nm, x, a, b)  = testCase ("arithCF-" ++ nm ++ "." ++ x) ((a .== b) `showsAs` "True")
+        cvtTest  (nm, x, a, b)  = testCase ("fpConverts.arithmetic-CF-" ++ nm ++ "." ++ x) (same (extract a) (extract b) `showsAs` "True")
+        cvtTestI (nm, x, a, b)  = testCase ("fpConverts.arithmetic-CF-" ++ nm ++ "." ++ x) ((a .== literal b) `showsAs` "True")
 
         mkTest1 (nm, (x, s))    = testCase ("arithCF-" ++ nm ++ "." ++ x) (s `showsAs` "True")
         mkTest2 (nm, (x, y, s)) = testCase ("arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y) (s `showsAs` "True")
diff --git a/SBVTestSuite/TestSuite/Basics/ArithSolver.hs b/SBVTestSuite/TestSuite/Basics/ArithSolver.hs
--- a/SBVTestSuite/TestSuite/Basics/ArithSolver.hs
+++ b/SBVTestSuite/TestSuite/Basics/ArithSolver.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.ArithSolver
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -93,18 +93,18 @@
                                       return $ literal r .== a `op` b
 
 genBoolTest :: String -> (forall a. Ord a => a -> a -> Bool) -> (forall a. OrdSymbolic a => a -> a -> SBool) -> [TestTree]
-genBoolTest nm op opS = map mkTest $  [(show x, show y, mkThm2  x y (x `op` y)) | x <- w8s,       y <- w8s                             ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- w16s,      y <- w16s                            ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- w32s,      y <- w32s                            ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- w64s,      y <- w64s                            ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- i8s,       y <- i8s                             ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- i16s,      y <- i16s                            ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- i32s,      y <- i32s                            ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- i64s,      y <- i64s                            ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- iUBs,      y <- iUBs                            ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- reducedCS, y <- reducedCS                       ]
-                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | x <- ss,        y <- ss, nm `elem` allowedStringComps]
-                                   ++ [(show x, show y, mkThm2L x y (x `op` y)) | x <- sl,        y <- sl, nm `elem` allowedListComps  ]
+genBoolTest nm op opS = map mkTest $  [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- w8s,       y <- w8s      ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- w16s,      y <- w16s     ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- w32s,      y <- w32s     ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- w64s,      y <- w64s     ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- i8s,       y <- i8s      ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- i16s,      y <- i16s     ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- i32s,      y <- i32s     ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- i64s,      y <- i64s     ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- iUBs,      y <- iUBs     ]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) |                               x <- reducedCS, y <- reducedCS]
+                                   ++ [(show x, show y, mkThm2  x y (x `op` y)) | nm `elem` allowedStringComps, x <- ss,        y <- ss       ]
+                                   ++ [(show x, show y, mkThm2L x y (x `op` y)) | nm `elem` allowedListComps  , x <- sl,        y <- sl       ]
   where -- Currently Z3 doesn't allow for string/list comparisons, so only test equals and distinct
         -- See: http://github.com/LeventErkok/sbv/issues/368 for tracking issue.
         allowedStringComps = ["==", "/="]
@@ -203,7 +203,7 @@
          yw16s = [0, 255, 256, 257, maxBound]
 
          mkTest (x, y, l, t) = testCase ("genShiftMixSize." ++ l ++ "." ++ x ++ "_" ++ y) (assert t)
-         mk :: (SymVal a, SymVal b) => (SBV a -> SBV b -> SBV a) -> a -> b -> a -> IO Bool
+         mk :: (Eq a, Eq b, SymVal a, SymVal b) => (SBV a -> SBV b -> SBV a) -> a -> b -> a -> IO Bool
          mk o x y r
           = isTheorem $ do a <- free "x"
                            b <- free "y"
@@ -299,9 +299,9 @@
 genDoubles = genIEEE754 "genDoubles" ds
 
 genIEEE754 :: (IEEEFloating a, Show a) => String -> [a] -> [TestTree]
-genIEEE754 origin vs =  map tst1 [("pred_"   ++ nm, x, y)    | (nm, x, y)    <- preds]
-                     ++ map tst1 [("unary_"  ++ nm, x, y)    | (nm, x, y)    <- uns]
-                     ++ map tst2 [("binary_" ++ nm, x, y, r) | (nm, x, y, r) <- bins]
+genIEEE754 origin vs =  [tst1 ("pred_"   ++ nm, x, y)    | (nm, x, y)    <- preds]
+                     ++ [tst1 ("unary_"  ++ nm, x, y)    | (nm, x, y)    <- uns]
+                     ++ [tst2 ("binary_" ++ nm, x, y, r) | (nm, x, y, r) <- bins]
   where uns =     [("abs",               show x, mkThm1 abs                   x  (abs x))                | x <- vs]
                ++ [("negate",            show x, mkThm1 negate                x  (negate x))             | x <- vs]
                ++ [("signum",            show x, mkThm1 signum                x  (signum x))             | x <- vs]
@@ -398,7 +398,7 @@
                      ]
 
 genFPConverts :: [TestTree]
-genFPConverts = map tst1 [("fpCast_" ++ nm, x, y) | (nm, x, y) <- converts]
+genFPConverts = [tst1 ("fpCast_" ++ nm, x, y) | (nm, x, y) <- converts]
   where converts =   [("toFP_Int8_ToFloat",     show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- i8s ]
                  ++  [("toFP_Int16_ToFloat",    show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- i16s]
                  ++  [("toFP_Int32_ToFloat",    show x, mkThmC (m toSFloat) x (fromRational (toRational x))) | x <- i32s]
@@ -425,35 +425,35 @@
                  ++  [("toFP_Integer_ToDouble", show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- iUBs]
                  ++  [("toFP_Real_ToDouble",    show x, mkThmC (m toSDouble) x (fromRational (toRational x))) | x <- rs  ]
 
-                 ++  [("fromFP_Float_ToInt8",    show x, mkThmC' (m fromSFloat :: SFloat -> SInt8)    x (((fromIntegral :: Integer -> Int8)    . fpRound0) x)) | x <- fs]
-                 ++  [("fromFP_Float_ToInt16",   show x, mkThmC' (m fromSFloat :: SFloat -> SInt16)   x (((fromIntegral :: Integer -> Int16)   . fpRound0) x)) | x <- fs]
-                 ++  [("fromFP_Float_ToInt32",   show x, mkThmC' (m fromSFloat :: SFloat -> SInt32)   x (((fromIntegral :: Integer -> Int32)   . fpRound0) x)) | x <- fs]
-                 ++  [("fromFP_Float_ToInt64",   show x, mkThmC' (m fromSFloat :: SFloat -> SInt64)   x (((fromIntegral :: Integer -> Int64)   . fpRound0) x)) | x <- fs]
-                 ++  [("fromFP_Float_ToWord8",   show x, mkThmC' (m fromSFloat :: SFloat -> SWord8)   x (((fromIntegral :: Integer -> Word8)   . fpRound0) x)) | x <- fs]
-                 ++  [("fromFP_Float_ToWord16",  show x, mkThmC' (m fromSFloat :: SFloat -> SWord16)  x (((fromIntegral :: Integer -> Word16)  . fpRound0) x)) | x <- fs]
-                 ++  [("fromFP_Float_ToWord32",  show x, mkThmC' (m fromSFloat :: SFloat -> SWord32)  x (((fromIntegral :: Integer -> Word32)  . fpRound0) x)) | x <- fs]
-                 ++  [("fromFP_Float_ToWord64",  show x, mkThmC' (m fromSFloat :: SFloat -> SWord64)  x (((fromIntegral :: Integer -> Word64)  . fpRound0) x)) | x <- fs]
-                 ++  [("fromFP_Float_ToFloat",   show x, mkThm1  (m fromSFloat :: SFloat -> SFloat)   x                                                    x ) | x <- fs]
-                 ++  [("fromFP_Float_ToDouble",  show x, mkThm1  (m fromSFloat :: SFloat -> SDouble)  x (                                           fp2fp  x)) | x <- fs]
-                 -- Neither Z3 nor MathSAT support Float->Integer/Float->Real conversion for the time being; so comment out.
-                 -- See GitHub issue: #191
-                 -- ++  [("fromFP_Float_ToInteger", show x, mkThmC' (m fromSFloat :: SFloat -> SInteger) x (((fromIntegral :: Integer -> Integer) . fpRound0) x)) | x <- fs]
-                 -- ++  [("fromFP_Float_ToReal",    show x, mkThmC' (m fromSFloat :: SFloat -> SReal)    x (                        (fromRational . fpRatio0) x)) | x <- fs]
+                 -- Conversions from floats are only well-defined if the input is in-bounds. So we just check round-trip for these.
+                 -- Also note that we clamp Int32/Word32/Int64/Word64 conversions further as floats become too sparse to handle those.
+                 ++  [("fromFP_Float_ToInt8",    show x, mkThmC' (m fromSFloat :: SFloat -> SInt8)     x ((round :: Float  -> Int8  )  x)) | i <- i8s,  let x = fromIntegral i]
+                 ++  [("fromFP_Float_ToInt16",   show x, mkThmC' (m fromSFloat :: SFloat -> SInt16)    x ((round :: Float  -> Int16 )  x)) | i <- i16s, let x = fromIntegral i]
+                 ++  [("fromFP_Float_ToInt32",   show x, mkThmC' (m fromSFloat :: SFloat -> SInt32)    x ((round :: Float  -> Int32 )  x)) | i <- i16s, let x = fromIntegral i]
+                 ++  [("fromFP_Float_ToInt64",   show x, mkThmC' (m fromSFloat :: SFloat -> SInt64)    x ((round :: Float  -> Int64 )  x)) | i <- i16s, let x = fromIntegral i]
+                 ++  [("fromFP_Float_ToWord8",   show x, mkThmC' (m fromSFloat :: SFloat -> SWord8)    x ((round :: Float  -> Word8 )  x)) | i <- w8s,  let x = fromIntegral i]
+                 ++  [("fromFP_Float_ToWord16",  show x, mkThmC' (m fromSFloat :: SFloat -> SWord16)   x ((round :: Float  -> Word16)  x)) | i <- w16s, let x = fromIntegral i]
+                 ++  [("fromFP_Float_ToWord32",  show x, mkThmC' (m fromSFloat :: SFloat -> SWord32)   x ((round :: Float  -> Word32)  x)) | i <- w16s, let x = fromIntegral i]
+                 ++  [("fromFP_Float_ToWord64",  show x, mkThmC' (m fromSFloat :: SFloat -> SWord64)   x ((round :: Float  -> Word64)  x)) | i <- w16s, let x = fromIntegral i]
 
-                 ++  [("fromFP_Double_ToInt8",    show x, mkThmC' (m fromSDouble :: SDouble -> SInt8)    x (((fromIntegral :: Integer -> Int8)    . fpRound0) x)) | x <- ds]
-                 ++  [("fromFP_Double_ToInt16",   show x, mkThmC' (m fromSDouble :: SDouble -> SInt16)   x (((fromIntegral :: Integer -> Int16)   . fpRound0) x)) | x <- ds]
-                 ++  [("fromFP_Double_ToInt32",   show x, mkThmC' (m fromSDouble :: SDouble -> SInt32)   x (((fromIntegral :: Integer -> Int32)   . fpRound0) x)) | x <- ds]
-                 ++  [("fromFP_Double_ToInt64",   show x, mkThmC' (m fromSDouble :: SDouble -> SInt64)   x (((fromIntegral :: Integer -> Int64)   . fpRound0) x)) | x <- ds]
-                 ++  [("fromFP_Double_ToWord8",   show x, mkThmC' (m fromSDouble :: SDouble -> SWord8)   x (((fromIntegral :: Integer -> Word8)   . fpRound0) x)) | x <- ds]
-                 ++  [("fromFP_Double_ToWord16",  show x, mkThmC' (m fromSDouble :: SDouble -> SWord16)  x (((fromIntegral :: Integer -> Word16)  . fpRound0) x)) | x <- ds]
-                 ++  [("fromFP_Double_ToWord32",  show x, mkThmC' (m fromSDouble :: SDouble -> SWord32)  x (((fromIntegral :: Integer -> Word32)  . fpRound0) x)) | x <- ds]
-                 ++  [("fromFP_Double_ToWord64",  show x, mkThmC' (m fromSDouble :: SDouble -> SWord64)  x (((fromIntegral :: Integer -> Word64)  . fpRound0) x)) | x <- ds]
-                 ++  [("fromFP_Double_ToFloat",   show x, mkThm1  (m fromSDouble :: SDouble -> SFloat)   x (                                            fp2fp x)) | x <- ds]
-                 ++  [("fromFP_Double_ToDouble",  show x, mkThm1  (m fromSDouble :: SDouble -> SDouble)  x                                                    x ) | x <- ds]
-                 -- Neither Z3 nor MathSAT support Float->Integer/Float->Real conversion for the time being; so comment out.
-                 -- See GitHub issue: #191
-                 -- ++  [("fromFP_Double_ToInteger", show x, mkThmC' (m fromSDouble :: SDouble -> SInteger) x (((fromIntegral :: Integer -> Integer) . fpRound0) x)) | x <- ds]
-                 -- ++  [("fromFP_Double_ToReal",    show x, mkThmC' (m fromSDouble :: SDouble -> SReal)    x (                        (fromRational . fpRatio0) x)) | x <- ds]
+                 ++  [("fromFP_Float_ToFloat",   show x, mkThm1  (m fromSFloat :: SFloat -> SFloat)    x                               x)  | x <- fs]
+                 ++  [("fromFP_Float_ToDouble",  show x, mkThm1  (m fromSFloat :: SFloat -> SDouble)   x (                    fp2fp    x)) | x <- fs]
+                 -- Neither Z3 nor MathSAT support Float->Integer/Float->Real conversion for the time being; so we skip those. See GitHub issue: #191
+
+                 -- Conversions from doubles are only well-defined if the input is in-bounds. So we just check round-trip for these.
+                 -- Also note that we clamp Int64/Word64 conversions further as floats become too sparse to handle those.
+                 ++  [("fromFP_Double_ToInt8",    show x, mkThmC' (m fromSDouble :: SDouble -> SInt8)   x ((round :: Double -> Int8  ) x)) | i <- i8s,  let x = fromIntegral i]
+                 ++  [("fromFP_Double_ToInt16",   show x, mkThmC' (m fromSDouble :: SDouble -> SInt16)  x ((round :: Double -> Int16 ) x)) | i <- i16s, let x = fromIntegral i]
+                 ++  [("fromFP_Double_ToInt32",   show x, mkThmC' (m fromSDouble :: SDouble -> SInt32)  x ((round :: Double -> Int32 ) x)) | i <- i32s, let x = fromIntegral i]
+                 ++  [("fromFP_Double_ToInt64",   show x, mkThmC' (m fromSDouble :: SDouble -> SInt64)  x ((round :: Double -> Int64 ) x)) | i <- i32s, let x = fromIntegral i]
+                 ++  [("fromFP_Double_ToWord8",   show x, mkThmC' (m fromSDouble :: SDouble -> SWord8)  x ((round :: Double -> Word8 ) x)) | i <- w8s,  let x = fromIntegral i]
+                 ++  [("fromFP_Double_ToWord16",  show x, mkThmC' (m fromSDouble :: SDouble -> SWord16) x ((round :: Double -> Word16) x)) | i <- w16s, let x = fromIntegral i]
+                 ++  [("fromFP_Double_ToWord32",  show x, mkThmC' (m fromSDouble :: SDouble -> SWord32) x ((round :: Double -> Word32) x)) | i <- w32s, let x = fromIntegral i]
+                 ++  [("fromFP_Double_ToWord64",  show x, mkThmC' (m fromSDouble :: SDouble -> SWord64) x ((round :: Double -> Word64) x)) | i <- w32s, let x = fromIntegral i]
+
+                 ++  [("fromFP_Double_ToFloat",   show x, mkThm1  (m fromSDouble :: SDouble -> SFloat)  x (                    fp2fp   x)) | x <- ds]
+                 ++  [("fromFP_Double_ToDouble",  show x, mkThm1  (m fromSDouble :: SDouble -> SDouble) x                              x ) | x <- ds]
+                 -- Neither Z3 nor MathSAT support Double->Integer/Double->Real conversion for the time being; so we skip those. See GitHub issue: #191
 
                  ++  [("reinterp_Word32_Float",  show x, mkThmC sWord32AsSFloat  x (RC.wordToFloat  x)) | x <- w32s]
                  ++  [("reinterp_Word64_Double", show x, mkThmC sWord64AsSDouble x (RC.wordToDouble x)) | x <- w64s]
diff --git a/SBVTestSuite/TestSuite/Basics/Assert.hs b/SBVTestSuite/TestSuite/Basics/Assert.hs
--- a/SBVTestSuite/TestSuite/Basics/Assert.hs
+++ b/SBVTestSuite/TestSuite/Basics/Assert.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.Assert
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/BarrelRotate.hs b/SBVTestSuite/TestSuite/Basics/BarrelRotate.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/BarrelRotate.hs
@@ -0,0 +1,97 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.BarrelRotate
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test barrel rotates.
+-----------------------------------------------------------------------------
+--
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE RankNTypes          #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+module TestSuite.Basics.BarrelRotate (tests)  where
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.BarrelRotate" [
+          goldenCapturedIO "barrelRotate_Left_Int8_Word8"     $ check $ checkLeft   @Int8   @Word8
+        , goldenCapturedIO "barrelRotate_Left_Int8_Word16"    $ check $ checkLeft   @Int8   @Word16
+        , goldenCapturedIO "barrelRotate_Left_Int8_Word32"    $ check $ checkLeft   @Int8   @Word32
+        , goldenCapturedIO "barrelRotate_Left_Int8_Word64"    $ check $ checkLeft   @Int8   @Word64
+        , goldenCapturedIO "barrelRotate_Left_Int16_Word8"    $ check $ checkLeft   @Int16  @Word8
+        , goldenCapturedIO "barrelRotate_Left_Int16_Word16"   $ check $ checkLeft   @Int16  @Word16
+        , goldenCapturedIO "barrelRotate_Left_Int16_Word32"   $ check $ checkLeft   @Int16  @Word32
+        , goldenCapturedIO "barrelRotate_Left_Int16_Word64"   $ check $ checkLeft   @Int16  @Word64
+        , goldenCapturedIO "barrelRotate_Left_Int32_Word8"    $ check $ checkLeft   @Int32  @Word8
+        , goldenCapturedIO "barrelRotate_Left_Int32_Word16"   $ check $ checkLeft   @Int32  @Word16
+        , goldenCapturedIO "barrelRotate_Left_Int32_Word32"   $ check $ checkLeft   @Int32  @Word32
+        , goldenCapturedIO "barrelRotate_Left_Int32_Word64"   $ check $ checkLeft   @Int32  @Word64
+        , goldenCapturedIO "barrelRotate_Left_Int64_Word8"    $ check $ checkLeft   @Int64  @Word8
+        , goldenCapturedIO "barrelRotate_Left_Int64_Word16"   $ check $ checkLeft   @Int64  @Word16
+        , goldenCapturedIO "barrelRotate_Left_Int64_Word32"   $ check $ checkLeft   @Int64  @Word32
+        , goldenCapturedIO "barrelRotate_Left_Int64_Word64"   $ check $ checkLeft   @Int64  @Word64
+        , goldenCapturedIO "barrelRotate_Left_Word8_Word8"    $ check $ checkLeft   @Word8  @Word8
+        , goldenCapturedIO "barrelRotate_Left_Word8_Word16"   $ check $ checkLeft   @Word8  @Word16
+        , goldenCapturedIO "barrelRotate_Left_Word8_Word32"   $ check $ checkLeft   @Word8  @Word32
+        , goldenCapturedIO "barrelRotate_Left_Word8_Word64"   $ check $ checkLeft   @Word8  @Word64
+        , goldenCapturedIO "barrelRotate_Left_Word16_Word8"   $ check $ checkLeft   @Word16 @Word8
+        , goldenCapturedIO "barrelRotate_Left_Word16_Word16"  $ check $ checkLeft   @Word16 @Word16
+        , goldenCapturedIO "barrelRotate_Left_Word16_Word32"  $ check $ checkLeft   @Word16 @Word32
+        , goldenCapturedIO "barrelRotate_Left_Word16_Word64"  $ check $ checkLeft   @Word16 @Word64
+        , goldenCapturedIO "barrelRotate_Left_Word32_Word8"   $ check $ checkLeft   @Word32 @Word8
+        , goldenCapturedIO "barrelRotate_Left_Word32_Word16"  $ check $ checkLeft   @Word32 @Word16
+        , goldenCapturedIO "barrelRotate_Left_Word32_Word32"  $ check $ checkLeft   @Word32 @Word32
+        , goldenCapturedIO "barrelRotate_Left_Word32_Word64"  $ check $ checkLeft   @Word32 @Word64
+        , goldenCapturedIO "barrelRotate_Left_Word64_Word8"   $ check $ checkLeft   @Word64 @Word8
+        , goldenCapturedIO "barrelRotate_Left_Word64_Word16"  $ check $ checkLeft   @Word64 @Word16
+        , goldenCapturedIO "barrelRotate_Left_Word64_Word32"  $ check $ checkLeft   @Word64 @Word32
+        , goldenCapturedIO "barrelRotate_Left_Word64_Word64"  $ check $ checkLeft   @Word64 @Word64
+        , goldenCapturedIO "barrelRotate_Right_Int8_Word8"    $ check $ checkRight  @Int8   @Word8
+        , goldenCapturedIO "barrelRotate_Right_Int8_Word16"   $ check $ checkRight  @Int8   @Word16
+        , goldenCapturedIO "barrelRotate_Right_Int8_Word32"   $ check $ checkRight  @Int8   @Word32
+        , goldenCapturedIO "barrelRotate_Right_Int8_Word64"   $ check $ checkRight  @Int8   @Word64
+        , goldenCapturedIO "barrelRotate_Right_Int16_Word8"   $ check $ checkRight  @Int16  @Word8
+        , goldenCapturedIO "barrelRotate_Right_Int16_Word16"  $ check $ checkRight  @Int16  @Word16
+        , goldenCapturedIO "barrelRotate_Right_Int16_Word32"  $ check $ checkRight  @Int16  @Word32
+        , goldenCapturedIO "barrelRotate_Right_Int16_Word64"  $ check $ checkRight  @Int16  @Word64
+        , goldenCapturedIO "barrelRotate_Right_Int32_Word8"   $ check $ checkRight  @Int32  @Word8
+        , goldenCapturedIO "barrelRotate_Right_Int32_Word16"  $ check $ checkRight  @Int32  @Word16
+        , goldenCapturedIO "barrelRotate_Right_Int32_Word32"  $ check $ checkRight  @Int32  @Word32
+        , goldenCapturedIO "barrelRotate_Right_Int32_Word64"  $ check $ checkRight  @Int32  @Word64
+        , goldenCapturedIO "barrelRotate_Right_Int64_Word8"   $ check $ checkRight  @Int64  @Word8
+        , goldenCapturedIO "barrelRotate_Right_Int64_Word16"  $ check $ checkRight  @Int64  @Word16
+        , goldenCapturedIO "barrelRotate_Right_Int64_Word32"  $ check $ checkRight  @Int64  @Word32
+        , goldenCapturedIO "barrelRotate_Right_Int64_Word64"  $ check $ checkRight  @Int64  @Word64
+        , goldenCapturedIO "barrelRotate_Right_Word8_Word8"   $ check $ checkRight  @Word8  @Word8
+        , goldenCapturedIO "barrelRotate_Right_Word8_Word16"  $ check $ checkRight  @Word8  @Word16
+        , goldenCapturedIO "barrelRotate_Right_Word8_Word32"  $ check $ checkRight  @Word8  @Word32
+        , goldenCapturedIO "barrelRotate_Right_Word8_Word64"  $ check $ checkRight  @Word8  @Word64
+        , goldenCapturedIO "barrelRotate_Right_Word16_Word8"  $ check $ checkRight  @Word16 @Word8
+        , goldenCapturedIO "barrelRotate_Right_Word16_Word16" $ check $ checkRight  @Word16 @Word16
+        , goldenCapturedIO "barrelRotate_Right_Word16_Word32" $ check $ checkRight  @Word16 @Word32
+        , goldenCapturedIO "barrelRotate_Right_Word16_Word64" $ check $ checkRight  @Word16 @Word64
+        , goldenCapturedIO "barrelRotate_Right_Word32_Word8"  $ check $ checkRight  @Word32 @Word8
+        , goldenCapturedIO "barrelRotate_Right_Word32_Word16" $ check $ checkRight  @Word32 @Word16
+        , goldenCapturedIO "barrelRotate_Right_Word32_Word32" $ check $ checkRight  @Word32 @Word32
+        , goldenCapturedIO "barrelRotate_Right_Word32_Word64" $ check $ checkRight  @Word32 @Word64
+        , goldenCapturedIO "barrelRotate_Right_Word64_Word8"  $ check $ checkRight  @Word64 @Word8
+        , goldenCapturedIO "barrelRotate_Right_Word64_Word16" $ check $ checkRight  @Word64 @Word16
+        , goldenCapturedIO "barrelRotate_Right_Word64_Word32" $ check $ checkRight  @Word64 @Word32
+        , goldenCapturedIO "barrelRotate_Right_Word64_Word64" $ check $ checkRight  @Word64 @Word64
+        ]
+    where -- NB. We use CVC4 for these tests as Z3 is rather slow!
+          check f gf = do r <- proveWith cvc4{verbose = True, redirectVerbose = Just gf} f
+                          appendFile gf ("\nFINAL:\n" ++ show r ++ "\nDONE!\n")
+
+          checkLeft :: forall a b. (SFiniteBits a, SFiniteBits b, SIntegral a, SIntegral b) => SBV a -> SBV b -> SBool
+          checkLeft x y = x `sBarrelRotateLeft` y .== x `sRotateLeft` y
+
+          checkRight :: forall a b. (SFiniteBits a, SFiniteBits b, SIntegral a, SIntegral b) => SBV a -> SBV b -> SBool
+          checkRight x y = x `sBarrelRotateRight` y .== x `sRotateRight` y
diff --git a/SBVTestSuite/TestSuite/Basics/BasicTests.hs b/SBVTestSuite/TestSuite/Basics/BasicTests.hs
--- a/SBVTestSuite/TestSuite/Basics/BasicTests.hs
+++ b/SBVTestSuite/TestSuite/Basics/BasicTests.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.BasicTests
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/BoundedList.hs b/SBVTestSuite/TestSuite/Basics/BoundedList.hs
--- a/SBVTestSuite/TestSuite/Basics/BoundedList.hs
+++ b/SBVTestSuite/TestSuite/Basics/BoundedList.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.BoundedList
--- Author    : Joel Burget
+-- Copyright : (c) Joel Burget
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/DynSign.hs b/SBVTestSuite/TestSuite/Basics/DynSign.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/DynSign.hs
@@ -0,0 +1,41 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.DynSign
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test case for <http://github.com/GaloisInc/cryptol/issues/566>
+-----------------------------------------------------------------------------
+
+module TestSuite.Basics.DynSign(tests) where
+
+import Utils.SBVTestFramework hiding (proveWith)
+
+import Data.SBV.Dynamic
+import Data.SBV.Internals  (genMkSymVar, unSBV)
+
+prop :: Symbolic SVal
+prop = do x <- unSBV <$> genMkSymVar w8 Nothing (Just "x")
+          let lhs = svUnsign (svSign x `svShiftRight` sfour)
+              rhs = svExtract 7 0    x `svShiftRight` ufour
+          return $ lhs `svEqual` rhs
+  where w8, i8 :: Kind
+        w8 = kindOf (undefined :: SWord8)
+        i8 = kindOf (undefined :: SInt8)
+        sfour = svInteger i8 4
+        ufour = svInteger w8 4
+
+checkSat :: ThmResult -> Assertion
+checkSat r = assert isThm
+  where isThm = case r of
+                  ThmResult Unsatisfiable{} -> return False :: IO Bool
+                  ThmResult Satisfiable{}   -> return True
+                  _                         -> error "checkSat: Unexpected result!"
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.DynSign"
+   [ testCase "dynSign" $ checkSat =<< proveWith z3 prop
+   ]
diff --git a/SBVTestSuite/TestSuite/Basics/Exceptions.hs b/SBVTestSuite/TestSuite/Basics/Exceptions.hs
--- a/SBVTestSuite/TestSuite/Basics/Exceptions.hs
+++ b/SBVTestSuite/TestSuite/Basics/Exceptions.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.Exceptions
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/GenBenchmark.hs b/SBVTestSuite/TestSuite/Basics/GenBenchmark.hs
--- a/SBVTestSuite/TestSuite/Basics/GenBenchmark.hs
+++ b/SBVTestSuite/TestSuite/Basics/GenBenchmark.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.GenBenchmark
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/Higher.hs b/SBVTestSuite/TestSuite/Basics/Higher.hs
--- a/SBVTestSuite/TestSuite/Basics/Higher.hs
+++ b/SBVTestSuite/TestSuite/Basics/Higher.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.Higher
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/Index.hs b/SBVTestSuite/TestSuite/Basics/Index.hs
--- a/SBVTestSuite/TestSuite/Basics/Index.hs
+++ b/SBVTestSuite/TestSuite/Basics/Index.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.Index
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/IteTest.hs b/SBVTestSuite/TestSuite/Basics/IteTest.hs
--- a/SBVTestSuite/TestSuite/Basics/IteTest.hs
+++ b/SBVTestSuite/TestSuite/Basics/IteTest.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.IteTest
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/List.hs b/SBVTestSuite/TestSuite/Basics/List.hs
--- a/SBVTestSuite/TestSuite/Basics/List.hs
+++ b/SBVTestSuite/TestSuite/Basics/List.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.List
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/ModelValidate.hs b/SBVTestSuite/TestSuite/Basics/ModelValidate.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/ModelValidate.hs
@@ -0,0 +1,61 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.ModelValidate
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Make sure the ABC bug is there, and a few other validate tests.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+
+module TestSuite.Basics.ModelValidate (testsABC, tests)  where
+
+import qualified Control.Exception as C
+import Data.List (isPrefixOf)
+
+import Utils.SBVTestFramework
+
+-- Test suite, this needs ABC
+testsABC :: TestTree
+testsABC = testGroup "Basics.ModelValidate.ABC" [
+             goldenCapturedIO "validate_0" badABC
+           ]
+    where badABC goldFile = do r <- satWith abc{verbose=True, redirectVerbose = Just goldFile, validateModel = True} $ forSome ["x"] $ \x -> x .< (10::SWord8)
+                               appendFile goldFile ("\nFINAL OUTPUT:\n" ++ show r ++ "\n")
+
+tests :: TestTree
+tests = testGroup "Basics.ModelValidate" [
+             goldenCapturedIO "validate_1" $ t  satWith    t1
+           , goldenCapturedIO "validate_2" $ t  satWith    t2
+           , goldenCapturedIO "validate_3" $ t  satWith    t3
+           , goldenCapturedIO "validate_4" $ t  proveWith  t3
+           , goldenCapturedIO "validate_5" $ t  satWith    t4
+           , goldenCapturedIO "validate_6" $ t  proveWith  t4
+           , goldenCapturedIO "validate_7" $ tE satWith    t5
+           ]
+    where t f test goldFile = do r <- f defaultSMTCfg{verbose=True, redirectVerbose = Just goldFile, validateModel = True} test
+                                 appendFile goldFile ("\nFINAL OUTPUT:\n" ++ show r ++ "\n")
+
+          tE f test goldFile = do r <- f defaultSMTCfg{verbose=True, redirectVerbose = Just goldFile, validateModel = True} test
+                                  appendFile goldFile ("\nFINAL OUTPUT:\n" ++ show r ++ "\n")
+                               `C.catch` (\(e::C.SomeException) -> appendFile goldFile ("\nEXCEPTION RAISED:\n" ++ pick (show e) ++ "\n"))
+              where pick s = unlines [l | l <- lines s, "***" `isPrefixOf` l]
+
+          t1 = forSome ["x"] $ \x -> fpAdd sRTZ x x   .== (x::SFloat)
+          t2 = forSome ["x"] $ \x -> fpFMA sRNE x x x .== (x::SFloat)
+
+          t3 = do x <- sInteger "x"
+                  constrain $ x .> x
+
+          t4 = do x <- sInteger "x"
+                  y <- sInteger "y"
+                  constrain $ x .> y
+                  constrain $ x .> 12
+                  return $ x .== y+3
+
+          t5 = do x <- exists "x"
+                  y <- forall "y"
+                  return $ fpIsPoint y .=> x .<= (y::SFloat)
diff --git a/SBVTestSuite/TestSuite/Basics/ProofTests.hs b/SBVTestSuite/TestSuite/Basics/ProofTests.hs
--- a/SBVTestSuite/TestSuite/Basics/ProofTests.hs
+++ b/SBVTestSuite/TestSuite/Basics/ProofTests.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.ProofTests
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/PseudoBoolean.hs b/SBVTestSuite/TestSuite/Basics/PseudoBoolean.hs
--- a/SBVTestSuite/TestSuite/Basics/PseudoBoolean.hs
+++ b/SBVTestSuite/TestSuite/Basics/PseudoBoolean.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.PseudoBoolean
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/QRem.hs b/SBVTestSuite/TestSuite/Basics/QRem.hs
--- a/SBVTestSuite/TestSuite/Basics/QRem.hs
+++ b/SBVTestSuite/TestSuite/Basics/QRem.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.QRem
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/Quantifiers.hs b/SBVTestSuite/TestSuite/Basics/Quantifiers.hs
--- a/SBVTestSuite/TestSuite/Basics/Quantifiers.hs
+++ b/SBVTestSuite/TestSuite/Basics/Quantifiers.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.Quantifiers
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/Recursive.hs b/SBVTestSuite/TestSuite/Basics/Recursive.hs
--- a/SBVTestSuite/TestSuite/Basics/Recursive.hs
+++ b/SBVTestSuite/TestSuite/Basics/Recursive.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.Recursive
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/Set.hs b/SBVTestSuite/TestSuite/Basics/Set.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Set.hs
@@ -0,0 +1,166 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Set
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test sets.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveAnyClass      #-}
+{-# LANGUAGE DeriveDataTypeable  #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving  #-}
+{-# LANGUAGE TemplateHaskell     #-}
+
+module TestSuite.Basics.Set (tests)  where
+
+import Data.SBV hiding (complement)
+import Data.SBV.Set
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework hiding (complement)
+
+data E = A | B | C
+mkSymbolicEnumeration ''E
+
+type SC = SSet  Char
+type RC = RCSet Char
+
+cSetAL :: SC
+cSetAL = fromList "hello"
+-- cSetBL :: SC
+-- cSetBL = fromList "there"
+
+cCharA :: SChar
+cCharA = literal 'e'
+
+-- The goal is to get rid of the following test vectors, and
+-- use the more interesting ones above. Unfortunately,
+-- there's a z3 bug in set-model generation that spits
+-- out models that we cannot parse. So, we're sticking
+-- to really simple examples in some cases here.
+cSetA :: SC
+cSetA = singleton $ literal 'a'
+-- cSetB :: SC
+-- cSetB = singleton $ literal 'b'
+
+-- Test suite
+tests :: TestTree
+tests = testGroup "Basics.Set" [
+          goldenCapturedIO "set_uninterp1"  $ ta setE1
+        , goldenCapturedIO "set_uninterp2"  $ tq setE2
+        , goldenCapturedIO "set_compl1"     $ tq $ templateU   cSetAL        complement
+        , goldenCapturedIO "set_union1"     $ tq $ templateB   cSetA  cSetA  union
+        , goldenCapturedIO "set_intersect1" $ tq $ templateB   cSetA  cSetA  intersection
+        , goldenCapturedIO "set_diff1"      $ tq $ templateB   cSetA  cSetA  difference
+        , goldenCapturedIO "set_empty1"     $ tq $ templateUB  cSetAL        isEmpty
+        , goldenCapturedIO "set_full1"      $ tq $ templateUB  cSetAL        isFull
+        , goldenCapturedIO "set_subset1"    $ tq $ templateBB  cSetA  cSetA  isSubsetOf
+        , goldenCapturedIO "set_psubset1"   $ tq $ templateBB  cSetA  cSetA  isProperSubsetOf
+        , goldenCapturedIO "set_disj1"      $ tq $ templateBB  cSetA  cSetA  disjoint
+        , goldenCapturedIO "set_insert1"    $ tq $ templateBE  cCharA cSetAL insert
+        , goldenCapturedIO "set_delete1"    $ tq $ templateBE  cCharA cSetAL delete
+        , goldenCapturedIO "set_member1"    $ tq $ templateBEB cCharA cSetAL member
+        , goldenCapturedIO "set_notMember1" $ tq $ templateBEB cCharA cSetAL notMember
+        ]
+    where ta tc goldFile    = record goldFile =<< tc defaultSMTCfg{verbose=True, redirectVerbose=Just goldFile}
+          tq tc goldFile    = record goldFile =<< runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just goldFile} tc
+          record goldFile r = appendFile goldFile ("\nFINAL:\n" ++ show r ++ "\nDONE!\n")
+
+setE1 :: SMTConfig -> IO AllSatResult
+setE1 cfg = allSatWith cfg $ \(_ :: SSet E) -> sTrue
+
+setE2 :: Symbolic (RCSet E, RCSet E)
+setE2 = do a :: SSet E <- sSet "a"
+           b :: SSet E <- sSet "b"
+
+           constrain $ distinct [a, b]
+
+           query $ do ensureSat
+                      (,) <$> getValue a <*> getValue b
+
+templateU :: SC -> (SC -> SC) -> Symbolic (RC, RC, RC, RC, RC)
+templateU is f = do a <- sSet "a"
+
+                    constrain $ a .== is
+
+                    let o1 = f a
+                        o2 = f o1
+                        o3 = o1 `intersection` a
+                        o4 = o1 `union`        a
+
+                    query $ do ensureSat
+                               (,,,,) <$> getValue a <*> getValue o1 <*> getValue o2 <*> getValue o3 <*> getValue o4
+
+templateB :: SC -> SC -> (SC -> SC -> SC) -> Symbolic (RC, RC, RC, RC, RC, RC)
+templateB is1 is2 f = do a <- sSet "a"
+                         b <- sSet "b"
+
+                         constrain $ a .== is1
+                         constrain $ b .== is2
+
+                         let o1 =            a `f`            b
+                             o2 =            a `f` complement b
+                             o3 = complement a `f`            b
+                             o4 = complement a `f` complement b
+
+                         query $ do ensureSat
+                                    (,,,,,) <$> getValue a <*> getValue b <*> getValue o1 <*> getValue o2 <*> getValue o3 <*> getValue o4
+
+templateUB :: SC -> (SC -> SBool) -> Symbolic (RC, Bool, Bool)
+templateUB is f = do a <- sSet "a"
+
+                     constrain $ a .== is
+
+                     let o1 = f a
+                         o2 = f (complement a)
+
+                     query $ do ensureSat
+                                (,,) <$> getValue a <*> getValue o1 <*> getValue o2
+
+templateBB :: SC -> SC -> (SC -> SC -> SBool) -> Symbolic (RC, RC, Bool, Bool, Bool, Bool)
+templateBB is1 is2 f = do a <- sSet "a"
+                          b <- sSet "b"
+
+                          constrain $ a .== is1
+                          constrain $ b .== is2
+
+                          let o1 =            a `f`            b
+                              o2 =            a `f` complement b
+                              o3 = complement a `f`            b
+                              o4 = complement a `f` complement b
+
+                          query $ do ensureSat
+                                     (,,,,,) <$> getValue a <*> getValue b <*> getValue o1 <*> getValue o2 <*> getValue o3 <*> getValue o4
+
+templateBE :: SChar -> SC -> (SChar -> SC -> SC) -> Symbolic (Char, RC, RC, RC)
+templateBE ic is f = do a <- sChar "a"
+                        b <- sSet  "b"
+
+                        constrain $ a .== ic
+                        constrain $ b .== is
+
+                        let o1 = a `f`            b
+                            o2 = a `f` complement b
+
+                        query $ do ensureSat
+                                   (,,,) <$> getValue a <*> getValue b <*> getValue o1 <*> getValue o2
+
+templateBEB :: SChar -> SC -> (SChar -> SC -> SBool) -> Symbolic (Char, RC, Bool, Bool)
+templateBEB ic is f = do a <- sChar "a"
+                         b <- sSet  "b"
+
+                         constrain $ a .== ic
+                         constrain $ b .== is
+
+                         let o1 = a `f`            b
+                             o2 = a `f` complement b
+
+                         query $ do ensureSat
+                                    (,,,) <$> getValue a <*> getValue b <*> getValue o1 <*> getValue o2
+
+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/SBVTestSuite/TestSuite/Basics/SmallShifts.hs b/SBVTestSuite/TestSuite/Basics/SmallShifts.hs
--- a/SBVTestSuite/TestSuite/Basics/SmallShifts.hs
+++ b/SBVTestSuite/TestSuite/Basics/SmallShifts.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.SmallShifts
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/SquashReals.hs b/SBVTestSuite/TestSuite/Basics/SquashReals.hs
--- a/SBVTestSuite/TestSuite/Basics/SquashReals.hs
+++ b/SBVTestSuite/TestSuite/Basics/SquashReals.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.SquashReals
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/String.hs b/SBVTestSuite/TestSuite/Basics/String.hs
--- a/SBVTestSuite/TestSuite/Basics/String.hs
+++ b/SBVTestSuite/TestSuite/Basics/String.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.String
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/Sum.hs b/SBVTestSuite/TestSuite/Basics/Sum.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/Sum.hs
@@ -0,0 +1,142 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.Sum
+-- Copyright : (c) Joel Burget
+--                 Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test the sum functions.
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+module TestSuite.Basics.Sum(tests)  where
+
+import Prelude hiding (either)
+import Control.Monad (unless, when)
+
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+import Data.SBV.Either
+import Data.SBV.Maybe  as M
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Sum" [
+      goldenCapturedIO "sumEitherSat"    $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumEitherSat    Sat
+    , goldenCapturedIO "sumBimapPlus"    $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumBimapPlus    Sat
+    , goldenCapturedIO "sumLiftEither"   $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumLiftEither   Sat
+    , goldenCapturedIO "sumMaybe"        $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumMaybe        Sat
+    , goldenCapturedIO "sumLiftMaybe"    $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumLiftMaybe    Sat
+    , goldenCapturedIO "sumMaybeBoth"    $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumMaybeBoth    Sat
+    , goldenCapturedIO "sumMergeMaybe1"  $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumMergeMaybe1  Sat
+    , goldenCapturedIO "sumMergeMaybe2"  $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumMergeMaybe2  Sat
+    , goldenCapturedIO "sumMergeEither1" $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumMergeEither1 Sat
+    , goldenCapturedIO "sumMergeEither2" $ \rf -> checkWith rf z3{redirectVerbose=Just rf} sumMergeEither2 Sat
+    ]
+
+checkWith :: FilePath -> SMTConfig -> Symbolic () -> CheckSatResult -> IO ()
+checkWith rf cfg props csExpected = runSMTWith cfg{verbose=True} $ do
+        _ <- props
+        query $ do cs <- checkSat
+                   unless (cs == csExpected) $
+                     case cs of
+                       Unsat -> error "Failed! Expected Sat, got UNSAT"
+                       Sat   -> getModel         >>= \r -> error $ "Failed! Expected Unsat, got SAT:\n" ++ show (SatResult (Satisfiable cfg r))
+                       Unk   -> getUnknownReason >>= \r -> error $ "Failed! Expected Unsat, got UNK:\n" ++ show r
+                   when (cs == Sat) $
+                       getModel >>= \m -> io $ appendFile rf $ "\nMODEL: " ++ show m ++ "\nDONE."
+
+
+-- Test 'either'
+sumEitherSat :: Symbolic ()
+sumEitherSat = do
+  x <- sEither @Integer @Bool "x"
+  constrain $ either (.> 0) sNot x
+
+-- Test 'bimap' and 'either'
+sumBimapPlus :: Symbolic ()
+sumBimapPlus = do
+  x <- sEither @Integer @Integer "x"
+  let x'    = bimap (+1) (+1) x
+      xval  = either id id x
+      x'val = either id id x'
+  constrain $ x'val .== xval + 1
+
+-- Test 'liftEither', 'sLeft', 'right', 'isLeft', and 'isRight'
+sumLiftEither :: Symbolic ()
+sumLiftEither = do
+  i <- sInteger "i"
+  c <- sChar "c"
+
+  constrain $ liftEither @Integer @Char (Left i) .== sLeft i
+  constrain $ isLeft     @Integer @Char (sLeft i)
+
+  constrain $ liftEither @Integer @Char (Right c) .== sRight c
+  constrain $ isRight    @Integer @Char (sRight c)
+
+-- Test 'sMaybe', 'map', 'isNothing', 'isJust', and 'maybe'
+sumMaybe :: Symbolic ()
+sumMaybe = do
+  x <- sMaybe @Integer "x"
+  let x' = M.map (+1) x
+  constrain $ isNothing x .== isNothing x'
+  constrain $ isJust x    .== isJust x'
+
+  let extract = M.maybe 0 id
+  constrain $ extract x .== extract x' - 1
+
+-- Test 'liftMaybe' and 'just'
+sumLiftMaybe :: Symbolic ()
+sumLiftMaybe = do
+  i <- sInteger "i"
+  constrain $ liftMaybe (Just i) .== sJust i
+  constrain $ sNothing ./= sJust i
+
+-- Test either/maybe together
+sumMaybeBoth :: Symbolic ()
+sumMaybeBoth = do
+   (x :: SEither Integer Integer) <- sEither_
+   (y :: SMaybe Integer)          <- sMaybe_
+
+   constrain $ isLeft x
+   constrain $ isJust y
+
+sumMergeMaybe1 :: Symbolic ()
+sumMergeMaybe1 = do
+   (x :: SMaybe Integer) <- sMaybe_
+   (y :: SMaybe Integer) <- sMaybe_
+   b  <- sBool_
+
+   constrain $ isNothing $ ite b x y
+
+sumMergeMaybe2 :: Symbolic ()
+sumMergeMaybe2 = do
+   (x :: SMaybe Integer) <- sMaybe_
+   (y :: SMaybe Integer) <- sMaybe_
+   b  <- sBool_
+
+   constrain $ isJust $ ite b x y
+
+sumMergeEither1 :: Symbolic ()
+sumMergeEither1 = do
+   (x :: SEither Integer Bool) <- sEither_
+   (y :: SEither Integer Bool) <- sEither_
+   b  <- sBool_
+
+   constrain $ isLeft $ ite b x y
+
+sumMergeEither2 :: Symbolic ()
+sumMergeEither2 = do
+   (x :: SEither Integer Bool) <- sEither_
+   (y :: SEither Integer Bool) <- sEither_
+   b  <- sBool_
+
+   constrain $ isRight $ ite b x y
+
+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/SBVTestSuite/TestSuite/Basics/TOut.hs b/SBVTestSuite/TestSuite/Basics/TOut.hs
--- a/SBVTestSuite/TestSuite/Basics/TOut.hs
+++ b/SBVTestSuite/TestSuite/Basics/TOut.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.TOut
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Basics/Tuple.hs b/SBVTestSuite/TestSuite/Basics/Tuple.hs
--- a/SBVTestSuite/TestSuite/Basics/Tuple.hs
+++ b/SBVTestSuite/TestSuite/Basics/Tuple.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Basics.Tuple
--- Author    : Joel Burget
+-- Copyright : (c) Joel Burget
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -100,7 +100,7 @@
                   constrain $ b .!! 4 .== sTrue
 
    query $ do
-     vTup2 :: STuple2 Word8 (E, Char, Float) <- freshVar "v2"
+     vTup2 :: STuple Word8 (E, Char, Float) <- freshVar "v2"
      constrain $ vTup2 .== literal (5, (C, 'A', 8.12))
 
      constrain $ vTup1 .== literal [(B, []), (A, [True, False]), (C, [False, False, False, False, True, False])]
diff --git a/SBVTestSuite/TestSuite/Basics/UISat.hs b/SBVTestSuite/TestSuite/Basics/UISat.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Basics/UISat.hs
@@ -0,0 +1,56 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Basics.UISat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing UI function sat examples
+-----------------------------------------------------------------------------
+
+module TestSuite.Basics.UISat(tests)  where
+
+import Data.SBV.Control
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.UIAllSat" [
+      goldenCapturedIO "uiSat_test1" $ \rf -> checkWith rf test1
+    , goldenCapturedIO "uiSat_test2" $ \rf -> checkWith rf test2
+    , goldenCapturedIO "uiSat_test3" $ \rf -> checkWith rf test3
+    ]
+
+cfg :: FilePath -> SMTConfig
+cfg rf = z3 { verbose             = True
+            , redirectVerbose     = Just rf
+            , allSatMaxModelCount = Just 80
+            , isNonModelVar       = (`elem` ["nx", "ny", "nz"])
+            }
+
+checkWith :: FilePath -> Goal -> IO ()
+checkWith rf prop = do r <- allSatWith (cfg rf) prop
+                       appendFile rf $ "\nRESULT: " ++ show r
+
+q1 :: SBool -> SBool
+q1 = uninterpret "q1"
+
+q2 :: SBool -> SBool -> SBool
+q2 = uninterpret "q2"
+
+test1 :: Goal
+test1 = do setLogic Logic_ALL
+           registerUISMTFunction q1
+
+test2 :: Goal
+test2 = do setLogic Logic_ALL
+           registerUISMTFunction q2
+
+test3 :: Goal
+test3 = do setLogic Logic_ALL
+           registerUISMTFunction q1
+           registerUISMTFunction q2
+
+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/SBVTestSuite/TestSuite/BitPrecise/BitTricks.hs b/SBVTestSuite/TestSuite/BitPrecise/BitTricks.hs
--- a/SBVTestSuite/TestSuite/BitPrecise/BitTricks.hs
+++ b/SBVTestSuite/TestSuite/BitPrecise/BitTricks.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.BitPrecise.BitTricks
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/BitPrecise/Legato.hs b/SBVTestSuite/TestSuite/BitPrecise/Legato.hs
--- a/SBVTestSuite/TestSuite/BitPrecise/Legato.hs
+++ b/SBVTestSuite/TestSuite/BitPrecise/Legato.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.BitPrecise.Legato
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/BitPrecise/MergeSort.hs b/SBVTestSuite/TestSuite/BitPrecise/MergeSort.hs
--- a/SBVTestSuite/TestSuite/BitPrecise/MergeSort.hs
+++ b/SBVTestSuite/TestSuite/BitPrecise/MergeSort.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.BitPrecise.MergeSort
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/BitPrecise/PrefixSum.hs b/SBVTestSuite/TestSuite/BitPrecise/PrefixSum.hs
--- a/SBVTestSuite/TestSuite/BitPrecise/PrefixSum.hs
+++ b/SBVTestSuite/TestSuite/BitPrecise/PrefixSum.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.BitPrecise.PrefixSum
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CRC/CCITT.hs b/SBVTestSuite/TestSuite/CRC/CCITT.hs
--- a/SBVTestSuite/TestSuite/CRC/CCITT.hs
+++ b/SBVTestSuite/TestSuite/CRC/CCITT.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CRC.CCITT
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CRC/CCITT_Unidir.hs b/SBVTestSuite/TestSuite/CRC/CCITT_Unidir.hs
--- a/SBVTestSuite/TestSuite/CRC/CCITT_Unidir.hs
+++ b/SBVTestSuite/TestSuite/CRC/CCITT_Unidir.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CRC.CCITT_Unidir
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CRC/GenPoly.hs b/SBVTestSuite/TestSuite/CRC/GenPoly.hs
--- a/SBVTestSuite/TestSuite/CRC/GenPoly.hs
+++ b/SBVTestSuite/TestSuite/CRC/GenPoly.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CRC.GenPoly
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CRC/Parity.hs b/SBVTestSuite/TestSuite/CRC/Parity.hs
--- a/SBVTestSuite/TestSuite/CRC/Parity.hs
+++ b/SBVTestSuite/TestSuite/CRC/Parity.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CRC.Parity
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CRC/USB5.hs b/SBVTestSuite/TestSuite/CRC/USB5.hs
--- a/SBVTestSuite/TestSuite/CRC/USB5.hs
+++ b/SBVTestSuite/TestSuite/CRC/USB5.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CRC.USB5
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/AddSub.hs b/SBVTestSuite/TestSuite/CodeGeneration/AddSub.hs
--- a/SBVTestSuite/TestSuite/CodeGeneration/AddSub.hs
+++ b/SBVTestSuite/TestSuite/CodeGeneration/AddSub.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CodeGeneration.AddSub
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/CRC_USB5.hs b/SBVTestSuite/TestSuite/CodeGeneration/CRC_USB5.hs
--- a/SBVTestSuite/TestSuite/CodeGeneration/CRC_USB5.hs
+++ b/SBVTestSuite/TestSuite/CodeGeneration/CRC_USB5.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CodeGeneration.CRC_USB5
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/CgTests.hs b/SBVTestSuite/TestSuite/CodeGeneration/CgTests.hs
--- a/SBVTestSuite/TestSuite/CodeGeneration/CgTests.hs
+++ b/SBVTestSuite/TestSuite/CodeGeneration/CgTests.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CodeGeneration.CgTests
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/Fibonacci.hs b/SBVTestSuite/TestSuite/CodeGeneration/Fibonacci.hs
--- a/SBVTestSuite/TestSuite/CodeGeneration/Fibonacci.hs
+++ b/SBVTestSuite/TestSuite/CodeGeneration/Fibonacci.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CodeGeneration.Fibonacci
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/Floats.hs b/SBVTestSuite/TestSuite/CodeGeneration/Floats.hs
--- a/SBVTestSuite/TestSuite/CodeGeneration/Floats.hs
+++ b/SBVTestSuite/TestSuite/CodeGeneration/Floats.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CodeGeneration.Floats
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/GCD.hs b/SBVTestSuite/TestSuite/CodeGeneration/GCD.hs
--- a/SBVTestSuite/TestSuite/CodeGeneration/GCD.hs
+++ b/SBVTestSuite/TestSuite/CodeGeneration/GCD.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CodeGeneration.GCD
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/PopulationCount.hs b/SBVTestSuite/TestSuite/CodeGeneration/PopulationCount.hs
--- a/SBVTestSuite/TestSuite/CodeGeneration/PopulationCount.hs
+++ b/SBVTestSuite/TestSuite/CodeGeneration/PopulationCount.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CodeGeneration.PopulationCount
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/CodeGeneration/Uninterpreted.hs b/SBVTestSuite/TestSuite/CodeGeneration/Uninterpreted.hs
--- a/SBVTestSuite/TestSuite/CodeGeneration/Uninterpreted.hs
+++ b/SBVTestSuite/TestSuite/CodeGeneration/Uninterpreted.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.CodeGeneration.Uninterpreted
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Crypto/AES.hs b/SBVTestSuite/TestSuite/Crypto/AES.hs
--- a/SBVTestSuite/TestSuite/Crypto/AES.hs
+++ b/SBVTestSuite/TestSuite/Crypto/AES.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Crypto.AES
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Crypto/RC4.hs b/SBVTestSuite/TestSuite/Crypto/RC4.hs
--- a/SBVTestSuite/TestSuite/Crypto/RC4.hs
+++ b/SBVTestSuite/TestSuite/Crypto/RC4.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Crypto.RC4
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Existentials/CRCPolynomial.hs b/SBVTestSuite/TestSuite/Existentials/CRCPolynomial.hs
--- a/SBVTestSuite/TestSuite/Existentials/CRCPolynomial.hs
+++ b/SBVTestSuite/TestSuite/Existentials/CRCPolynomial.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Existentials.CRCPolynomial
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/GenTest/GenTests.hs b/SBVTestSuite/TestSuite/GenTest/GenTests.hs
--- a/SBVTestSuite/TestSuite/GenTest/GenTests.hs
+++ b/SBVTestSuite/TestSuite/GenTest/GenTests.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.GenTest.GenTests
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Optimization/AssertWithPenalty.hs b/SBVTestSuite/TestSuite/Optimization/AssertWithPenalty.hs
--- a/SBVTestSuite/TestSuite/Optimization/AssertWithPenalty.hs
+++ b/SBVTestSuite/TestSuite/Optimization/AssertWithPenalty.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Optimization.AssertWithPenalty
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Optimization/Basics.hs b/SBVTestSuite/TestSuite/Optimization/Basics.hs
--- a/SBVTestSuite/TestSuite/Optimization/Basics.hs
+++ b/SBVTestSuite/TestSuite/Optimization/Basics.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Optimization.Basics
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Optimization/Combined.hs b/SBVTestSuite/TestSuite/Optimization/Combined.hs
--- a/SBVTestSuite/TestSuite/Optimization/Combined.hs
+++ b/SBVTestSuite/TestSuite/Optimization/Combined.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Optimization.Combined
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Optimization/ExtensionField.hs b/SBVTestSuite/TestSuite/Optimization/ExtensionField.hs
--- a/SBVTestSuite/TestSuite/Optimization/ExtensionField.hs
+++ b/SBVTestSuite/TestSuite/Optimization/ExtensionField.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Optimization.ExtensionField
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Optimization/Floats.hs b/SBVTestSuite/TestSuite/Optimization/Floats.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/Floats.hs
@@ -0,0 +1,64 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.Floats
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines, floats
+-----------------------------------------------------------------------------
+
+module TestSuite.Optimization.Floats (tests) where
+
+import Control.Monad (when)
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.Floats"
+    [ goldenVsStringShow "optFloat1" $ optimizeWith z3{printBase=16} Independent (p True)
+    , goldenVsStringShow "optFloat2" $ optimizeWith z3{printBase=16} Independent (p False)
+    , goldenVsStringShow "optFloat3" $ optimizeWith z3{printBase=16} Lexicographic q
+    , goldenVsStringShow "optFloat4" $ optimizeWith z3{printBase=16} Lexicographic r
+    ]
+
+p :: Bool -> Goal
+p reqPoint = do x <- sFloat  "x"
+                y <- sDouble "y"
+
+                when reqPoint $ do constrain $ fpIsPoint x
+                                   constrain $ fpIsPoint y
+
+                minimize "min-x" x
+                maximize "max-x" x
+                minimize "min-y" y
+                maximize "max-y" y
+
+q :: Goal
+q = do x <- sFloat "x"
+       y <- sFloat "y"
+
+       constrain $ fpIsPoint x
+       constrain $ fpIsPoint y
+       constrain $ x .== y
+       constrain $ x .> 0
+       constrain $ fpIsPoint $ x+y
+
+       maximize "metric-max-x+y" $ observe "max-x+y" (x+y)
+
+r :: Goal
+r = do x <- sFloat "x"
+       y <- sFloat "y"
+
+       constrain $ fpIsPoint x
+       constrain $ fpIsPoint y
+       constrain $ x .== y
+       constrain $ x .> 0
+       constrain $ fpIsPoint $ x+y
+
+       minimize "metric-min-x+y" $ observe "min-x+y" (x+y)
+
+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/SBVTestSuite/TestSuite/Optimization/NoOpt.hs b/SBVTestSuite/TestSuite/Optimization/NoOpt.hs
--- a/SBVTestSuite/TestSuite/Optimization/NoOpt.hs
+++ b/SBVTestSuite/TestSuite/Optimization/NoOpt.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Optimization.NoOpt
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Optimization/Quantified.hs b/SBVTestSuite/TestSuite/Optimization/Quantified.hs
--- a/SBVTestSuite/TestSuite/Optimization/Quantified.hs
+++ b/SBVTestSuite/TestSuite/Optimization/Quantified.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Optimization.Quantified
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Optimization/Reals.hs b/SBVTestSuite/TestSuite/Optimization/Reals.hs
--- a/SBVTestSuite/TestSuite/Optimization/Reals.hs
+++ b/SBVTestSuite/TestSuite/Optimization/Reals.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Optimization.Reals
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Optimization/Tuples.hs b/SBVTestSuite/TestSuite/Optimization/Tuples.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Optimization/Tuples.hs
@@ -0,0 +1,35 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Optimization.Tuples
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Test suite for optimization routines, tuples
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables  #-}
+
+module TestSuite.Optimization.Tuples (tests) where
+
+import Data.SBV.Tuple
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Optimization.Tuples"
+    [ goldenVsStringShow "optTuple1" $ optimize Lexicographic t1
+    ]
+
+t1 :: Goal
+t1 = do p :: STuple Integer Integer <- sTuple "p"
+
+        constrain $ (p^._1) `inRange` (0, 100)
+        constrain $ (p^._2) `inRange` (0, 100)
+
+        constrain $ p^._1 - p^._2 .< 10
+        constrain $ p^._1 + p^._2 .== 80
+
+        maximize "max-p" p
diff --git a/SBVTestSuite/TestSuite/Overflows/Arithmetic.hs b/SBVTestSuite/TestSuite/Overflows/Arithmetic.hs
--- a/SBVTestSuite/TestSuite/Overflows/Arithmetic.hs
+++ b/SBVTestSuite/TestSuite/Overflows/Arithmetic.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Overflows.Arithmetic
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Overflows/Casts.hs b/SBVTestSuite/TestSuite/Overflows/Casts.hs
--- a/SBVTestSuite/TestSuite/Overflows/Casts.hs
+++ b/SBVTestSuite/TestSuite/Overflows/Casts.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Overflows.Casts
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Polynomials/Polynomials.hs b/SBVTestSuite/TestSuite/Polynomials/Polynomials.hs
--- a/SBVTestSuite/TestSuite/Polynomials/Polynomials.hs
+++ b/SBVTestSuite/TestSuite/Polynomials/Polynomials.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Polynomials.Polynomials
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/Coins.hs b/SBVTestSuite/TestSuite/Puzzles/Coins.hs
--- a/SBVTestSuite/TestSuite/Puzzles/Coins.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/Coins.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.Coins
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/Counts.hs b/SBVTestSuite/TestSuite/Puzzles/Counts.hs
--- a/SBVTestSuite/TestSuite/Puzzles/Counts.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/Counts.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.Counts
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/DogCatMouse.hs b/SBVTestSuite/TestSuite/Puzzles/DogCatMouse.hs
--- a/SBVTestSuite/TestSuite/Puzzles/DogCatMouse.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/DogCatMouse.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.DogCatMouse
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/Euler185.hs b/SBVTestSuite/TestSuite/Puzzles/Euler185.hs
--- a/SBVTestSuite/TestSuite/Puzzles/Euler185.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/Euler185.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.Euler185
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/MagicSquare.hs b/SBVTestSuite/TestSuite/Puzzles/MagicSquare.hs
--- a/SBVTestSuite/TestSuite/Puzzles/MagicSquare.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/MagicSquare.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.MagicSquare
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/NQueens.hs b/SBVTestSuite/TestSuite/Puzzles/NQueens.hs
--- a/SBVTestSuite/TestSuite/Puzzles/NQueens.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/NQueens.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.NQueens
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/PowerSet.hs b/SBVTestSuite/TestSuite/Puzzles/PowerSet.hs
--- a/SBVTestSuite/TestSuite/Puzzles/PowerSet.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/PowerSet.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.PowerSet
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/Sudoku.hs b/SBVTestSuite/TestSuite/Puzzles/Sudoku.hs
--- a/SBVTestSuite/TestSuite/Puzzles/Sudoku.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/Sudoku.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.Sudoku
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/Temperature.hs b/SBVTestSuite/TestSuite/Puzzles/Temperature.hs
--- a/SBVTestSuite/TestSuite/Puzzles/Temperature.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/Temperature.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.Temperature
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Puzzles/U2Bridge.hs b/SBVTestSuite/TestSuite/Puzzles/U2Bridge.hs
--- a/SBVTestSuite/TestSuite/Puzzles/U2Bridge.hs
+++ b/SBVTestSuite/TestSuite/Puzzles/U2Bridge.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Puzzles.U2Bridge
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -31,4 +31,4 @@
  where act     = do b <- exists_; p1 <- exists_; p2 <- exists_; return (b, p1, p2)
        count n = numberOfModels $ isValid `fmap` mapM (const act) [1..(n::Int)]
        slv n   = rearrange `fmap` allSat (isValid `fmap` mapM (const act) [1..(n::Int)])
-       rearrange (AllSatResult (b1, b2, ms)) = AllSatResult (b1, b2, sortOn (show . SatResult) ms)
+       rearrange (AllSatResult (b1, b2, b3, ms)) = AllSatResult (b1, b2, b3, sortOn (show . SatResult) ms)
diff --git a/SBVTestSuite/TestSuite/Queries/BadOption.hs b/SBVTestSuite/TestSuite/Queries/BadOption.hs
--- a/SBVTestSuite/TestSuite/Queries/BadOption.hs
+++ b/SBVTestSuite/TestSuite/Queries/BadOption.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.BadOption
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/BasicQuery.hs b/SBVTestSuite/TestSuite/Queries/BasicQuery.hs
--- a/SBVTestSuite/TestSuite/Queries/BasicQuery.hs
+++ b/SBVTestSuite/TestSuite/Queries/BasicQuery.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.BasicQuery
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -46,7 +46,6 @@
        setOption $ ProduceUnsatCores True
        setOption $ ProduceUnsatAssumptions True
        setOption $ ProduceProofs True
-       setOption $ ProduceInterpolants True
        setOption $ RandomSeed 123
        setOption $ ProduceAssertions True
        setOption $ OptionKeyword ":smt.mbqi" ["true"]
@@ -62,7 +61,6 @@
                   _ <- getOption ProduceAssertions
                   _ <- getOption ProduceAssignments
                   _ <- getOption ProduceProofs
-                  _ <- getOption ProduceInterpolants
                   _ <- getOption ProduceUnsatAssumptions
                   _ <- getOption ProduceUnsatCores
                   _ <- getOption RandomSeed
diff --git a/SBVTestSuite/TestSuite/Queries/Enums.hs b/SBVTestSuite/TestSuite/Queries/Enums.hs
--- a/SBVTestSuite/TestSuite/Queries/Enums.hs
+++ b/SBVTestSuite/TestSuite/Queries/Enums.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Enums
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/FreshVars.hs b/SBVTestSuite/TestSuite/Queries/FreshVars.hs
--- a/SBVTestSuite/TestSuite/Queries/FreshVars.hs
+++ b/SBVTestSuite/TestSuite/Queries/FreshVars.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.FreshVars
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Int_ABC.hs b/SBVTestSuite/TestSuite/Queries/Int_ABC.hs
--- a/SBVTestSuite/TestSuite/Queries/Int_ABC.hs
+++ b/SBVTestSuite/TestSuite/Queries/Int_ABC.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Int_ABC
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Int_Boolector.hs b/SBVTestSuite/TestSuite/Queries/Int_Boolector.hs
--- a/SBVTestSuite/TestSuite/Queries/Int_Boolector.hs
+++ b/SBVTestSuite/TestSuite/Queries/Int_Boolector.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Int_Boolector
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Int_CVC4.hs b/SBVTestSuite/TestSuite/Queries/Int_CVC4.hs
--- a/SBVTestSuite/TestSuite/Queries/Int_CVC4.hs
+++ b/SBVTestSuite/TestSuite/Queries/Int_CVC4.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Int_CVC4
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Int_Mathsat.hs b/SBVTestSuite/TestSuite/Queries/Int_Mathsat.hs
--- a/SBVTestSuite/TestSuite/Queries/Int_Mathsat.hs
+++ b/SBVTestSuite/TestSuite/Queries/Int_Mathsat.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Int_Mathsat
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Int_Yices.hs b/SBVTestSuite/TestSuite/Queries/Int_Yices.hs
--- a/SBVTestSuite/TestSuite/Queries/Int_Yices.hs
+++ b/SBVTestSuite/TestSuite/Queries/Int_Yices.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Int_Yices
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Int_Z3.hs b/SBVTestSuite/TestSuite/Queries/Int_Z3.hs
--- a/SBVTestSuite/TestSuite/Queries/Int_Z3.hs
+++ b/SBVTestSuite/TestSuite/Queries/Int_Z3.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Int_Z3
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Interpolants.hs b/SBVTestSuite/TestSuite/Queries/Interpolants.hs
--- a/SBVTestSuite/TestSuite/Queries/Interpolants.hs
+++ b/SBVTestSuite/TestSuite/Queries/Interpolants.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Interpolants
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Lists.hs b/SBVTestSuite/TestSuite/Queries/Lists.hs
--- a/SBVTestSuite/TestSuite/Queries/Lists.hs
+++ b/SBVTestSuite/TestSuite/Queries/Lists.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Lists
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Strings.hs b/SBVTestSuite/TestSuite/Queries/Strings.hs
--- a/SBVTestSuite/TestSuite/Queries/Strings.hs
+++ b/SBVTestSuite/TestSuite/Queries/Strings.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Strings
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Queries/Sums.hs b/SBVTestSuite/TestSuite/Queries/Sums.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/Sums.hs
@@ -0,0 +1,175 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  TestSuite.Queries.Sums
+-- Copyright   :  (c) Joel Burget
+--                    Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- Testing sum queries
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications    #-}
+
+module TestSuite.Queries.Sums (tests)  where
+
+import Data.SBV
+import Data.SBV.Control
+import Data.SBV.Either as E
+import Data.SBV.Maybe  as M
+
+import qualified Data.SBV.List as L
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.QuerySums"
+    [ goldenCapturedIO "query_Sums"            $ testQuery querySums
+    , goldenCapturedIO "query_ListOfSum"       $ testQuery queryListOfSum
+    , goldenCapturedIO "query_Maybe"           $ testQuery queryMaybe
+    , goldenCapturedIO "query_ListOfMaybe"     $ testQuery queryListOfMaybe
+    , goldenCapturedIO "query_SumMaybeBoth"    $ testQuery querySumMaybeBoth
+    , goldenCapturedIO "query_sumMergeMaybe1"  $ testQuery querySumMergeMaybe1
+    , goldenCapturedIO "query_sumMergeMaybe2"  $ testQuery querySumMergeMaybe2
+    , goldenCapturedIO "query_sumMergeEither1" $ testQuery querySumMergeEither1
+    , goldenCapturedIO "query_sumMergeEither2" $ testQuery querySumMergeEither2
+    ]
+
+testQuery :: Show a => Symbolic a -> FilePath -> IO ()
+testQuery t rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} t
+                    appendFile rf ("\nFINAL OUTPUT:\n" ++ show r ++ "\n")
+
+querySums :: Symbolic (Either Integer Char)
+querySums = do
+  a <- sEither @Integer @Char "a"
+
+  constrain $ E.either (.== 1) (const sFalse) a
+
+  query $ do
+    _ <- checkSat
+
+    av <- getValue a
+
+    if av == Left 1
+       then return av
+       else error $ "Didn't expect this: " ++ show av
+
+queryListOfSum :: Symbolic [Either Integer Char]
+queryListOfSum = do
+  lst <- sList @(Either Integer Char) "lst"
+  constrain $ L.length lst .== 2
+  constrain $ isLeft $ L.head lst
+  constrain $ isRight $ L.head $ L.tail lst
+
+  query $ do
+    _  <- checkSat
+    av <- getValue lst
+
+    case av of
+      [Left _, Right _] -> return av
+      _                 -> error $ "Didn't expect this: " ++ show av
+
+queryMaybe :: Symbolic (Maybe Integer)
+queryMaybe = do
+  a <- sMaybe @Integer "a"
+
+  constrain $ M.maybe sFalse (.== 1) a
+
+  query $ do
+    _ <- checkSat
+
+    av <- getValue a
+
+    if av == Just 1
+       then return av
+       else error $ "Didn't expect this: " ++ show av
+
+queryListOfMaybe :: Symbolic [Maybe Char]
+queryListOfMaybe = do
+  lst <- sList @(Maybe Char) "lst"
+  constrain $ L.length lst .== 2
+  constrain $ isJust $ L.head lst
+  constrain $ isNothing $ L.head $ L.tail lst
+
+  query $ do
+    _  <- checkSat
+    av <- getValue lst
+
+    case av of
+      [Just _, Nothing] -> return av
+      _                 -> error $ "Didn't expect this: " ++ show av
+
+querySumMaybeBoth :: Symbolic (Either Integer Integer, Maybe Integer)
+querySumMaybeBoth = query $ do
+        (x :: SEither Integer Integer) <- freshVar_
+        (y :: SMaybe Integer)          <- freshVar_
+
+        constrain $ isLeft x
+        constrain $ isJust y
+
+        _ <- checkSat
+        xv <- getValue x
+        yv <- getValue y
+        return (xv, yv)
+
+querySumMergeMaybe1 :: Symbolic (Maybe Integer, Maybe Integer, Bool)
+querySumMergeMaybe1 = query $ do
+   (x :: SMaybe Integer) <- freshVar_
+   (y :: SMaybe Integer) <- freshVar_
+   b  <- freshVar_
+
+   constrain $ isNothing $ ite b x y
+
+   _ <- checkSat
+   xv <- getValue x
+   yv <- getValue y
+   bv <- getValue b
+   return (xv, yv, bv)
+
+querySumMergeMaybe2 :: Symbolic (Maybe Integer, Maybe Integer, Bool)
+querySumMergeMaybe2 = query $ do
+   (x :: SMaybe Integer) <- freshVar_
+   (y :: SMaybe Integer) <- freshVar_
+   b  <- freshVar_
+
+   constrain $ isJust $ ite b x y
+
+   _ <- checkSat
+   xv <- getValue x
+   yv <- getValue y
+   bv <- getValue b
+   return (xv, yv, bv)
+
+querySumMergeEither1 :: Symbolic (Either Integer Bool, Either Integer Bool, Bool)
+querySumMergeEither1 = query $ do
+   (x :: SEither Integer Bool) <- freshVar_
+   (y :: SEither Integer Bool) <- freshVar_
+   b  <- freshVar_
+
+   constrain $ isLeft $ ite b x y
+
+   _ <- checkSat
+   xv <- getValue x
+   yv <- getValue y
+   bv <- getValue b
+   return (xv, yv, bv)
+
+querySumMergeEither2 :: Symbolic (Either Integer Bool, Either Integer Bool, Bool)
+querySumMergeEither2 = query $ do
+   (x :: SEither Integer Bool) <- freshVar_
+   (y :: SEither Integer Bool) <- freshVar_
+   b  <- freshVar_
+
+   constrain $ isRight $ ite b x y
+
+   _ <- checkSat
+   xv <- getValue x
+   yv <- getValue y
+   bv <- getValue b
+   return (xv, yv, bv)
+
+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/SBVTestSuite/TestSuite/Queries/UISat.hs b/SBVTestSuite/TestSuite/Queries/UISat.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/UISat.hs
@@ -0,0 +1,62 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.UISat
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing UI function sat examples via queries
+-----------------------------------------------------------------------------
+
+module TestSuite.Queries.UISat(tests)  where
+
+import Control.Monad (unless, when)
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Basics.Queries.UIAllSat" [
+      goldenCapturedIO "query_uiSat_test1" $ \rf -> checkWith rf (mkCfg rf) test1 Sat
+    , goldenCapturedIO "query_uiSat_test2" $ \rf -> checkWith rf (mkCfg rf) test2 Sat
+    ]
+
+mkCfg :: FilePath -> SMTConfig
+mkCfg rf = z3 { verbose             = True
+              , redirectVerbose     = Just rf
+              , allSatMaxModelCount = Just 80
+              , isNonModelVar       = (`elem` ["nx", "ny", "nz"])
+              }
+
+checkWith :: FilePath -> SMTConfig -> Symbolic () -> CheckSatResult -> IO ()
+checkWith rf cfg props csExpected = runSMTWith cfg{verbose=True} $ do
+        _ <- props
+        query $ do cs <- checkSat
+                   unless (cs == csExpected) $
+                     case cs of
+                       Unsat -> error "Failed! Expected Sat, got UNSAT"
+                       Sat   -> getModel         >>= \r -> error $ "Failed! Expected Unsat, got SAT:\n" ++ show (SatResult (Satisfiable cfg r))
+                       Unk   -> getUnknownReason >>= \r -> error $ "Failed! Expected Unsat, got UNK:\n" ++ show r
+                   when (cs == Sat) $
+                       getModel >>= \m -> io $ appendFile rf $ "\nMODEL: " ++ show m ++ "\nDONE."
+
+q1 :: SBool -> SBool
+q1 = uninterpret "q1"
+
+q2 :: SBool -> SBool -> SBool
+q2 = uninterpret "q2"
+
+test1 :: Symbolic ()
+test1 = do setLogic Logic_ALL
+           constrain $ q1 sFalse .== sFalse
+           constrain $ q1 sTrue  .== sTrue
+
+test2 :: Symbolic ()
+test2 = do setLogic Logic_ALL
+           constrain $ q2 sFalse sTrue  .== sFalse
+           constrain $ q2 sTrue  sTrue  .== sTrue
+           constrain $ q2 sTrue  sFalse .== sTrue
diff --git a/SBVTestSuite/TestSuite/Queries/UISatEx.hs b/SBVTestSuite/TestSuite/Queries/UISatEx.hs
new file mode 100644
--- /dev/null
+++ b/SBVTestSuite/TestSuite/Queries/UISatEx.hs
@@ -0,0 +1,87 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module    : TestSuite.Queries.UISatEx
+-- Copyright : (c) Levent Erkok
+-- License   : BSD3
+-- Maintainer: erkokl@gmail.com
+-- Stability : experimental
+--
+-- Testing uninterpreted function extraction
+-----------------------------------------------------------------------------
+
+{-# LANGUAGE OverloadedLists   #-}
+{-# LANGUAGE OverloadedStrings #-}
+
+module TestSuite.Queries.UISatEx where
+
+import Data.SBV.Control
+
+import Utils.SBVTestFramework
+
+-- Test suite
+tests :: TestTree
+tests =
+  testGroup "Queries.UISatEx"
+    [ goldenCapturedIO "query_uisatex1" testQuery1
+    , goldenCapturedIO "query_uisatex2" testQuery2
+    ]
+
+testQuery1 :: FilePath -> IO ()
+testQuery1 rf = do r <- satWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf} core
+                   appendFile rf ("\n FINAL:\n" ++ show r ++ "\nDONE!\n")
+
+testQuery2 :: FilePath -> IO ()
+testQuery2 rf = do r <- runSMTWith defaultSMTCfg{verbose=True, redirectVerbose=Just rf, allSatMaxModelCount = Just 5} qCore
+                   appendFile rf ("\n FINAL:\n" ++ show r ++ "\nDONE!\n")
+  where qCore = do core
+                   let q6 :: SInteger -> SBool
+                       q6 = uninterpret "q6"
+                   constrain $ q6 0 .=> q6 0
+                   query $ do registerUISMTFunction q6 -- Not really necessary, but testing it doesn't break anything
+                              ensureSat
+                              qv1 <- getFunction q1
+                              qv2 <- getFunction q2
+                              qv3 <- getFunction q3
+                              qv4 <- getFunction q4
+                              qv5 <- getFunction q5
+                              qv6 <- getFunction q6
+                              return (qv1, qv2, qv3, qv4, qv5, qv6)
+
+q1 :: SInteger -> SInteger
+q1 = uninterpret "q1"
+
+q2 :: SBool -> SInteger -> SInteger
+q2 = uninterpret "q2"
+
+q3 :: SFloat -> SBool -> SInteger -> SFloat
+q3 = uninterpret "q3"
+
+q4 :: SChar -> SString -> SFloat
+q4 = uninterpret "q4"
+
+q5 :: SList Integer -> SList Float -> SInteger
+q5 = uninterpret "q5"
+
+core :: Goal
+core = do x <- sInteger_
+          constrain $ q1 2    .== 12
+          constrain $ q1 3    .== 75
+          constrain $ q1 (-3) .== 9
+          constrain $ q1 x    .== x+1
+
+          registerUISMTFunction q2 -- Not really necessary, but testing it doesn't break anything
+          constrain $ q2 sTrue 3   .== 5
+          constrain $ q2 sFalse 7  .== 6
+          constrain $ q2 sFalse 12 .== 3
+
+          constrain $                    q3 8.6 sTrue  12  .== 8.6
+          constrain $ fpIsNegativeZero $ q3 9.6 sTrue  121
+          constrain $                    q3 9.6 sFalse 8   .== 1/0
+
+          constrain $ q4 (literal 'c') "hey" .== 78
+          constrain $ q4 (literal 'c') "tey" .== 92
+          constrain $ q4 (literal 'r') "foo" .== 3.5
+
+          constrain $ q5 [1,2,3] [8.2, 3] .== 7
+          constrain $ q5 [9,5]   [8.2, 9] .== 21
+          constrain $ q5 [5]     [8.2, 0] .== 210
diff --git a/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs b/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs
--- a/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs
+++ b/SBVTestSuite/TestSuite/Queries/Uninterpreted.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Queries.Uninterpreted
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/QuickCheck/QC.hs b/SBVTestSuite/TestSuite/QuickCheck/QC.hs
--- a/SBVTestSuite/TestSuite/QuickCheck/QC.hs
+++ b/SBVTestSuite/TestSuite/QuickCheck/QC.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.QuickCheck.QC
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Transformers/SymbolicEval.hs b/SBVTestSuite/TestSuite/Transformers/SymbolicEval.hs
--- a/SBVTestSuite/TestSuite/Transformers/SymbolicEval.hs
+++ b/SBVTestSuite/TestSuite/Transformers/SymbolicEval.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Transformers.SymbolicEval
--- Author    : Brian Schroeder
+-- Copyright : (c) Brian Schroeder
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/AUF.hs b/SBVTestSuite/TestSuite/Uninterpreted/AUF.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/AUF.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/AUF.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Uninterpreted.AUF
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs b/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Axioms.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Uninterpreted.Axioms
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Function.hs b/SBVTestSuite/TestSuite/Uninterpreted/Function.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/Function.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Function.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Uninterpreted.Function
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs b/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Sort.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Uninterpreted.Sort
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs b/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs
--- a/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs
+++ b/SBVTestSuite/TestSuite/Uninterpreted/Uninterpreted.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : TestSuite.Uninterpreted.Uninterpreted
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/SBVTestSuite/Utils/SBVTestFramework.hs b/SBVTestSuite/Utils/SBVTestFramework.hs
--- a/SBVTestSuite/Utils/SBVTestFramework.hs
+++ b/SBVTestSuite/Utils/SBVTestFramework.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Utils.SBVTestFramework
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
@@ -60,7 +60,7 @@
 
 import System.FilePath ((</>), (<.>))
 
-import Data.SBV.Internals (runSymbolic, Symbolic, Result, SBVRunMode(..), IStage(..), SBV(..), SVal(..), showModel, SMTModel(..))
+import Data.SBV.Internals (runSymbolic, Symbolic, Result, SBVRunMode(..), IStage(..), SBV(..), SVal(..), showModel, SMTModel(..), QueryContext(..))
 
 ---------------------------------------------------------------------------------------
 -- Test environment; continuous integration
@@ -161,14 +161,21 @@
          cleanUp = BS.filter (/= slashr)
          slashr  = fromIntegral (ord '\r')
 
--- | Count the number of models
+-- | Count the number of models. It's not kosher to
+-- call this function if you provided a max-model count
+-- that was hit, or the search was stopped because the
+-- solver said 'Unknown' at some point.
 numberOfModels :: Provable a => a -> IO Int
-numberOfModels p = do AllSatResult (_, _, rs) <- allSat p
-                      return $ length rs
+numberOfModels p = do AllSatResult (maxHit, _, unk, rs) <- allSat p
+                      let l = length rs
+                      case (unk, maxHit) of
+                        (True, _)   -> error $ "Data.SBV.numberOfModels: Search was stopped because solver said 'Unknown'. At this point, we saw: " ++ show l ++ " model(s)."
+                        (_,   True) -> error $ "Data.SBV.numberOfModels: Search was stopped because the user-specified max-model count was hit at " ++ show l ++ " model(s)."
+                        _           -> return l
 
 -- | Symbolicly run a SAT instance using the default config
 runSAT :: Symbolic a -> IO Result
-runSAT cmp = snd <$> runSymbolic (SMTMode ISetup True defaultSMTCfg) cmp
+runSAT cmp = snd <$> runSymbolic (SMTMode QueryInternal ISetup True defaultSMTCfg) cmp
 
 -- | Turn provable to an assertion, theorem case
 assertIsThm :: Provable a => a -> Assertion
@@ -187,7 +194,7 @@
 assertIsntSat p = assert (fmap not (isSatisfiable p))
 
 -- | Quick-check a unary function, creating one version for constant folding, and another for solver
-qc1 :: (SymVal a, SymVal b, Show a, QC.Arbitrary a, SMTValue b) => String -> (a -> b) -> (SBV a -> SBV b) -> [TestTree]
+qc1 :: (Eq a, SymVal a, SymVal b, Show a, QC.Arbitrary a, Eq b, SMTValue b) => String -> (a -> b) -> (SBV a -> SBV b) -> [TestTree]
 qc1 nm opC opS = [cf, sm]
    where cf = QC.testProperty (nm ++ ".constantFold") $ do
                         i <- free "i"
@@ -228,8 +235,8 @@
                                    ]
 
                             model = case result of
-                                      Right v -> showModel defaultSMTCfg (SMTModel [] (vals ++ [getCV "Result" (literal v)]))
-                                      Left  e -> showModel defaultSMTCfg (SMTModel [] vals) ++ "\n" ++ e
+                                      Right v -> showModel defaultSMTCfg (SMTModel [] Nothing (vals ++ [getCV "Result" (literal v)]) [])
+                                      Left  e -> showModel defaultSMTCfg (SMTModel [] Nothing vals []) ++ "\n" ++ e
 
                         QC.monitor (QC.counterexample model)
 
@@ -239,7 +246,7 @@
 
 
 -- | Quick-check a binary function, creating one version for constant folding, and another for solver
-qc2 :: (SymVal a, SymVal b, SymVal c, Show a, Show b, QC.Arbitrary a, QC.Arbitrary b, SMTValue c) => String -> (a -> b -> c) -> (SBV a -> SBV b -> SBV c) -> [TestTree]
+qc2 :: (Eq a, Eq b, SymVal a, SymVal b, SymVal c, Show a, Show b, QC.Arbitrary a, QC.Arbitrary b, Eq c, SMTValue c) => String -> (a -> b -> c) -> (SBV a -> SBV b -> SBV c) -> [TestTree]
 qc2 nm opC opS = [cf, sm]
    where cf = QC.testProperty (nm ++ ".constantFold") $ do
                         i1 <- free "i1"
@@ -286,8 +293,8 @@
                                    ]
 
                             model = case result of
-                                      Right v -> showModel defaultSMTCfg (SMTModel [] (vals ++ [getCV "Result" (literal v)]))
-                                      Left  e -> showModel defaultSMTCfg (SMTModel [] vals) ++ "\n" ++ e
+                                      Right v -> showModel defaultSMTCfg (SMTModel [] Nothing (vals ++ [getCV "Result" (literal v)]) [])
+                                      Left  e -> showModel defaultSMTCfg (SMTModel [] Nothing vals []) ++ "\n" ++ e
 
                         QC.monitor (QC.counterexample model)
 
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module    : Setup
--- Author    : Levent Erkok
+-- Copyright : (c) Levent Erkok
 -- License   : BSD3
 -- Maintainer: erkokl@gmail.com
 -- Stability : experimental
diff --git a/sbv.cabal b/sbv.cabal
--- a/sbv.cabal
+++ b/sbv.cabal
@@ -1,5 +1,5 @@
 Name:          sbv
-Version:       8.0
+Version:       8.1
 Category:      Formal Methods, Theorem Provers, Bit vectors, Symbolic Computation, Math, SMT
 Synopsis:      SMT Based Verification: Symbolic Haskell theorem prover using SMT solving.
 Description:   Express properties about Haskell programs and automatically prove them using SMT
@@ -72,8 +72,11 @@
   Exposed-modules : Data.SBV
                   , Data.SBV.Control
                   , Data.SBV.Dynamic
+                  , Data.SBV.Either
                   , Data.SBV.Internals
                   , Data.SBV.List
+                  , Data.SBV.Maybe
+                  , Data.SBV.Set
                   , Data.SBV.String
                   , Data.SBV.Tuple
                   , Data.SBV.Char
@@ -88,6 +91,7 @@
                   , Data.SBV.Tools.Polynomial
                   , Data.SBV.Tools.Range
                   , Data.SBV.Tools.STree
+                  , Data.SBV.Tools.WeakestPreconditions
                   , Data.SBV.Trans
                   , Data.SBV.Trans.Control
                   , Documentation.SBV.Examples.BitPrecise.BitTricks
@@ -115,17 +119,26 @@
                   , Documentation.SBV.Examples.Misc.Auxiliary
                   , Documentation.SBV.Examples.Misc.NoDiv0
                   , Documentation.SBV.Examples.Misc.Polynomials
+                  , Documentation.SBV.Examples.Misc.SetAlgebra
                   , Documentation.SBV.Examples.Misc.SoftConstrain
                   , Documentation.SBV.Examples.Misc.Tuple
                   , Documentation.SBV.Examples.Misc.Word4
+                  , Documentation.SBV.Examples.Optimization.Enumerate
+                  , Documentation.SBV.Examples.Optimization.ExtField
                   , Documentation.SBV.Examples.Optimization.LinearOpt
                   , Documentation.SBV.Examples.Optimization.Production
                   , Documentation.SBV.Examples.Optimization.VM
-                  , Documentation.SBV.Examples.Optimization.ExtField
                   , Documentation.SBV.Examples.ProofTools.BMC
                   , Documentation.SBV.Examples.ProofTools.Fibonacci
                   , Documentation.SBV.Examples.ProofTools.Strengthen
                   , Documentation.SBV.Examples.ProofTools.Sum
+                  , Documentation.SBV.Examples.WeakestPreconditions.Append
+                  , Documentation.SBV.Examples.WeakestPreconditions.Fib
+                  , Documentation.SBV.Examples.WeakestPreconditions.GCD
+                  , Documentation.SBV.Examples.WeakestPreconditions.IntDiv
+                  , Documentation.SBV.Examples.WeakestPreconditions.IntSqrt
+                  , Documentation.SBV.Examples.WeakestPreconditions.Length
+                  , Documentation.SBV.Examples.WeakestPreconditions.Sum
                   , Documentation.SBV.Examples.Puzzles.Birthday
                   , Documentation.SBV.Examples.Puzzles.Coins
                   , Documentation.SBV.Examples.Puzzles.Counts
@@ -153,6 +166,7 @@
                   , Documentation.SBV.Examples.Uninterpreted.AUF
                   , Documentation.SBV.Examples.Uninterpreted.Deduce
                   , Documentation.SBV.Examples.Uninterpreted.Function
+                  , Documentation.SBV.Examples.Uninterpreted.Multiply
                   , Documentation.SBV.Examples.Uninterpreted.Shannon
                   , Documentation.SBV.Examples.Uninterpreted.Sort
                   , Documentation.SBV.Examples.Uninterpreted.UISortAllSat
@@ -223,24 +237,30 @@
                   , TestSuite.Basics.ArithNoSolver
                   , TestSuite.Basics.ArithSolver
                   , TestSuite.Basics.Assert
+                  , TestSuite.Basics.BarrelRotate
                   , TestSuite.Basics.BasicTests
                   , TestSuite.Basics.BoundedList
+                  , TestSuite.Basics.DynSign
                   , TestSuite.Basics.Exceptions
                   , TestSuite.Basics.GenBenchmark
                   , TestSuite.Basics.Higher
                   , TestSuite.Basics.Index
                   , TestSuite.Basics.IteTest
+                  , TestSuite.Basics.List
+                  , TestSuite.Basics.ModelValidate
                   , TestSuite.Basics.ProofTests
                   , TestSuite.Basics.PseudoBoolean
                   , TestSuite.Basics.QRem
                   , TestSuite.Basics.Quantifiers
                   , TestSuite.Basics.Recursive
+                  , TestSuite.Basics.Set
                   , TestSuite.Basics.SmallShifts
                   , TestSuite.Basics.SquashReals
                   , TestSuite.Basics.String
-                  , TestSuite.Basics.List
+                  , TestSuite.Basics.Sum
                   , TestSuite.Basics.TOut
                   , TestSuite.Basics.Tuple
+                  , TestSuite.Basics.UISat
                   , TestSuite.BitPrecise.BitTricks
                   , TestSuite.BitPrecise.Legato
                   , TestSuite.BitPrecise.MergeSort
@@ -266,9 +286,11 @@
                   , TestSuite.Optimization.Basics
                   , TestSuite.Optimization.Combined
                   , TestSuite.Optimization.ExtensionField
+                  , TestSuite.Optimization.Floats
+                  , TestSuite.Optimization.NoOpt
                   , TestSuite.Optimization.Quantified
                   , TestSuite.Optimization.Reals
-                  , TestSuite.Optimization.NoOpt
+                  , TestSuite.Optimization.Tuples
                   , TestSuite.Overflows.Arithmetic
                   , TestSuite.Overflows.Casts
                   , TestSuite.Polynomials.Polynomials
@@ -295,8 +317,11 @@
                   , TestSuite.Queries.Interpolants
                   , TestSuite.Queries.Lists
                   , TestSuite.Queries.Strings
+                  , TestSuite.Queries.Sums
                   , TestSuite.Queries.Tuples
                   , TestSuite.Queries.Uninterpreted
+                  , TestSuite.Queries.UISat
+                  , TestSuite.Queries.UISatEx
                   , TestSuite.QuickCheck.QC
                   , TestSuite.Transformers.SymbolicEval
                   , TestSuite.Uninterpreted.AUF
